From 6ee8768fe2a2d8a95c787be16a36248d4d84a2c1 Mon Sep 17 00:00:00 2001 From: Mark Diekhans Date: Mon, 6 Apr 2020 06:09:29 -0700 Subject: [PATCH] point users to https://github.com/ComparativeGenomicsToolkit/sonLib --- .gitignore | 7 - .gitmodules | 0 .travis.yml | 24 - C/Makefile | 63 - C/impl/avl.c | 883 ------- C/impl/bioioC.c | 578 ----- C/impl/commonC.c | 1089 --------- C/impl/fastCMaths.c | 151 -- C/impl/hashTableC.c | 307 --- C/impl/hashTableC_itr.c | 184 -- C/impl/jsmn.c | 334 --- C/impl/lz4.c | 907 ------- C/impl/lz4.h | 128 - C/impl/lz4hc.c | 730 ------ C/impl/lz4hc.h | 60 - C/impl/pairwiseAlignment.c | 241 -- C/impl/sonLibAlign.c | 15 - C/impl/sonLibCache.c | 285 --- C/impl/sonLibCommon.c | 204 -- C/impl/sonLibCompression.c | 216 -- C/impl/sonLibConnectivity.c | 783 ------ C/impl/sonLibEulerTour.c | 731 ------ C/impl/sonLibExcept.c | 121 - C/impl/sonLibFile.c | 127 - C/impl/sonLibGlobalsInternal.h | 38 - C/impl/sonLibHash.c | 224 -- C/impl/sonLibKVDatabase.c | 557 ----- C/impl/sonLibKVDatabaseConf.c | 330 --- C/impl/sonLibKVDatabasePrivate.h | 83 - C/impl/sonLibKVDatabase_BigRecordFile.c | 330 --- C/impl/sonLibKVDatabase_KyotoTycoon.cpp | 588 ----- C/impl/sonLibKVDatabase_MySql.c | 518 ---- C/impl/sonLibKVDatabase_TokyoCabinet.c | 337 --- C/impl/sonLibList.c | 316 --- C/impl/sonLibListPrivate.h | 23 - C/impl/sonLibMath.c | 40 - C/impl/sonLibNaiveConnectivity.c | 332 --- C/impl/sonLibRandom.c | 67 - C/impl/sonLibSet.c | 215 -- C/impl/sonLibSortedSet.c | 318 --- C/impl/sonLibString.c | 258 -- C/impl/sonLibTreap.c | 524 ----- C/impl/sonLibTree.c | 425 ---- C/impl/sonLibTuples.c | 204 -- C/impl/stGraph.c | 109 - C/impl/stJson.c | 78 - C/impl/stMatrix.c | 126 - C/impl/stPhylogeny.c | 2090 ----------------- C/impl/stPosetAlignment.c | 202 -- C/impl/stSafeC.c | 132 -- C/impl/stThreadPool.c | 207 -- C/impl/stUnionFind.c | 110 - C/inc/avl.h | 127 - C/inc/bioioC.h | 133 -- C/inc/commonC.h | 301 --- C/inc/fastCMaths.h | 131 -- C/inc/hashTableC.h | 210 -- C/inc/hashTableC_itr.h | 117 - C/inc/hashTablePrivateC.h | 95 - C/inc/jsmn.h | 98 - C/inc/pairwiseAlignment.h | 64 - C/inc/sonLib.h | 47 - C/inc/sonLibAlign.h | 199 -- C/inc/sonLibCache.h | 70 - C/inc/sonLibCommon.h | 132 -- C/inc/sonLibCompression.h | 51 - C/inc/sonLibConnectivity.h | 108 - C/inc/sonLibEulerTour.h | 48 - C/inc/sonLibExcept.h | 232 -- C/inc/sonLibFile.h | 67 - C/inc/sonLibHash.h | 143 -- C/inc/sonLibKVDatabase.h | 191 -- C/inc/sonLibKVDatabaseConf.h | 110 - C/inc/sonLibList.h | 216 -- C/inc/sonLibMath.h | 35 - C/inc/sonLibNaiveConnectivity.h | 21 - C/inc/sonLibRandom.h | 68 - C/inc/sonLibSet.h | 142 -- C/inc/sonLibSortedSet.h | 178 -- C/inc/sonLibString.h | 127 - C/inc/sonLibTreap.h | 52 - C/inc/sonLibTree.h | 146 -- C/inc/sonLibTuples.h | 99 - C/inc/sonLibTypes.h | 82 - C/inc/stGraph.h | 50 - C/inc/stJson.h | 47 - C/inc/stMatrix.h | 77 - C/inc/stPhylogeny.h | 228 -- C/inc/stPosetAlignment.h | 44 - C/inc/stSafeC.h | 116 - C/inc/stSpimapLayer.h | 19 - C/inc/stThreadPool.h | 52 - C/inc/stUnionFind.h | 32 - C/tests/allTests.c | 75 - C/tests/cigarsTest.c | 50 - C/tests/fastaCTest.c | 41 - C/tests/kt_connect_test.cpp | 152 -- C/tests/kvDatabaseTest.c | 607 ----- C/tests/kvDatabaseTestCommon.c | 148 -- C/tests/kvDatabaseTestCommon.h | 15 - C/tests/sonLibAlignTest.c | 36 - C/tests/sonLibCacheTest.c | 146 -- C/tests/sonLibCommonTest.c | 75 - C/tests/sonLibCompressionTest.c | 88 - C/tests/sonLibConnectivityTests.c | 427 ---- C/tests/sonLibDoubleTuplesTest.c | 118 - C/tests/sonLibEdgeContainerTests.c | 84 - C/tests/sonLibEulerTest.c | 164 -- C/tests/sonLibExceptTest.c | 156 -- C/tests/sonLibFileTest.c | 162 -- C/tests/sonLibGlobalsTest.h | 33 - C/tests/sonLibGraphTest.c | 74 - C/tests/sonLibHashTest.c | 206 -- C/tests/sonLibIntTuplesTest.c | 114 - C/tests/sonLibListTest.c | 290 --- C/tests/sonLibPosetAlignmentTest.c | 233 -- C/tests/sonLibRandomTest.c | 238 -- C/tests/sonLibSetTest.c | 457 ---- C/tests/sonLibSortedSetTest.c | 517 ---- C/tests/sonLibStringTest.c | 184 -- C/tests/sonLibTreapTest.c | 140 -- C/tests/sonLibTreeTest.c | 269 --- C/tests/sonLibTuplesTest.c | 114 - C/tests/stMatrixTest.c | 159 -- C/tests/stPhylogenyTest.c | 1491 ------------ C/tests/stThreadPoolTest.c | 86 - C/tests/stUnionFindTest.c | 103 - LICENSE.txt | 19 - Makefile | 28 - README.md | 25 +- __init__.py | 5 - allTests.py | 57 - bioio.py | 1316 ----------- bioioTest.py | 301 --- cigarsTest.py | 72 - doc/INSTALL.txt | 12 - doc/README | 89 - doc/abbreviations.txt | 0 externalTools/Makefile | 20 - externalTools/cutest/AllTests.c | 25 - externalTools/cutest/CuTest.c | 342 --- externalTools/cutest/CuTest.h | 116 - externalTools/cutest/CuTestTest.c | 709 ------ externalTools/cutest/Makefile | 18 - externalTools/cutest/README.txt | 211 -- externalTools/cutest/index.html | 196 -- externalTools/cutest/license.txt | 38 - externalTools/cutest/make-tests.sh | 55 - externalTools/cutest/style.css | 21 - externalTools/quicktree_1.1/Makefile | 55 - externalTools/quicktree_1.1/README | 45 - externalTools/quicktree_1.1/bin/.gitignore | 0 externalTools/quicktree_1.1/include/align.h | 96 - .../quicktree_1.1/include/aln2dist.h | 36 - .../quicktree_1.1/include/aln2tree.h | 39 - .../quicktree_1.1/include/buildtree.h | 124 - .../quicktree_1.1/include/buildtree.h~ | 124 - externalTools/quicktree_1.1/include/cluster.h | 174 -- .../quicktree_1.1/include/dist2tree.h | 40 - .../quicktree_1.1/include/distancemat.h | 189 -- externalTools/quicktree_1.1/include/options.h | 52 - .../quicktree_1.1/include/sequence.h | 70 - externalTools/quicktree_1.1/include/tree.h | 390 --- externalTools/quicktree_1.1/include/util.h | 108 - externalTools/quicktree_1.1/obj/.gitignore | 0 externalTools/quicktree_1.1/src/align.c | 347 --- externalTools/quicktree_1.1/src/aln2dist.c | 109 - externalTools/quicktree_1.1/src/aln2tree.c | 147 -- externalTools/quicktree_1.1/src/buildtree.c | 750 ------ externalTools/quicktree_1.1/src/cluster.c | 357 --- externalTools/quicktree_1.1/src/dist2tree.c | 77 - externalTools/quicktree_1.1/src/distancemat.c | 450 ---- .../quicktree_1.1/src/distancemat_merops.c | 460 ---- externalTools/quicktree_1.1/src/options.c | 96 - externalTools/quicktree_1.1/src/quicktree.c | 207 -- externalTools/quicktree_1.1/src/sequence.c | 131 -- externalTools/quicktree_1.1/src/tree.c | 956 -------- externalTools/quicktree_1.1/src/util.c | 153 -- include.mk | 123 - kvdbTest.py | 31 - misc.py | 156 -- nxnewick.py | 202 -- nxnewickTest.py | 71 - nxtree.py | 185 -- nxtreeTest.py | 103 - setup.py | 36 - sonLib_daemonize.py | 103 - tree.py | 792 ------- treeTest.py | 219 -- unitTest.py | 24 - 190 files changed, 3 insertions(+), 40205 deletions(-) delete mode 100644 .gitignore delete mode 100644 .gitmodules delete mode 100644 .travis.yml delete mode 100644 C/Makefile delete mode 100644 C/impl/avl.c delete mode 100644 C/impl/bioioC.c delete mode 100644 C/impl/commonC.c delete mode 100644 C/impl/fastCMaths.c delete mode 100644 C/impl/hashTableC.c delete mode 100644 C/impl/hashTableC_itr.c delete mode 100644 C/impl/jsmn.c delete mode 100644 C/impl/lz4.c delete mode 100644 C/impl/lz4.h delete mode 100644 C/impl/lz4hc.c delete mode 100644 C/impl/lz4hc.h delete mode 100644 C/impl/pairwiseAlignment.c delete mode 100644 C/impl/sonLibAlign.c delete mode 100644 C/impl/sonLibCache.c delete mode 100644 C/impl/sonLibCommon.c delete mode 100644 C/impl/sonLibCompression.c delete mode 100644 C/impl/sonLibConnectivity.c delete mode 100644 C/impl/sonLibEulerTour.c delete mode 100644 C/impl/sonLibExcept.c delete mode 100644 C/impl/sonLibFile.c delete mode 100644 C/impl/sonLibGlobalsInternal.h delete mode 100644 C/impl/sonLibHash.c delete mode 100644 C/impl/sonLibKVDatabase.c delete mode 100644 C/impl/sonLibKVDatabaseConf.c delete mode 100644 C/impl/sonLibKVDatabasePrivate.h delete mode 100644 C/impl/sonLibKVDatabase_BigRecordFile.c delete mode 100644 C/impl/sonLibKVDatabase_KyotoTycoon.cpp delete mode 100644 C/impl/sonLibKVDatabase_MySql.c delete mode 100644 C/impl/sonLibKVDatabase_TokyoCabinet.c delete mode 100644 C/impl/sonLibList.c delete mode 100644 C/impl/sonLibListPrivate.h delete mode 100644 C/impl/sonLibMath.c delete mode 100644 C/impl/sonLibNaiveConnectivity.c delete mode 100644 C/impl/sonLibRandom.c delete mode 100644 C/impl/sonLibSet.c delete mode 100644 C/impl/sonLibSortedSet.c delete mode 100644 C/impl/sonLibString.c delete mode 100644 C/impl/sonLibTreap.c delete mode 100644 C/impl/sonLibTree.c delete mode 100644 C/impl/sonLibTuples.c delete mode 100644 C/impl/stGraph.c delete mode 100644 C/impl/stJson.c delete mode 100644 C/impl/stMatrix.c delete mode 100644 C/impl/stPhylogeny.c delete mode 100644 C/impl/stPosetAlignment.c delete mode 100644 C/impl/stSafeC.c delete mode 100644 C/impl/stThreadPool.c delete mode 100644 C/impl/stUnionFind.c delete mode 100644 C/inc/avl.h delete mode 100644 C/inc/bioioC.h delete mode 100644 C/inc/commonC.h delete mode 100644 C/inc/fastCMaths.h delete mode 100644 C/inc/hashTableC.h delete mode 100644 C/inc/hashTableC_itr.h delete mode 100644 C/inc/hashTablePrivateC.h delete mode 100644 C/inc/jsmn.h delete mode 100644 C/inc/pairwiseAlignment.h delete mode 100644 C/inc/sonLib.h delete mode 100644 C/inc/sonLibAlign.h delete mode 100644 C/inc/sonLibCache.h delete mode 100644 C/inc/sonLibCommon.h delete mode 100644 C/inc/sonLibCompression.h delete mode 100644 C/inc/sonLibConnectivity.h delete mode 100644 C/inc/sonLibEulerTour.h delete mode 100644 C/inc/sonLibExcept.h delete mode 100644 C/inc/sonLibFile.h delete mode 100644 C/inc/sonLibHash.h delete mode 100644 C/inc/sonLibKVDatabase.h delete mode 100644 C/inc/sonLibKVDatabaseConf.h delete mode 100644 C/inc/sonLibList.h delete mode 100644 C/inc/sonLibMath.h delete mode 100644 C/inc/sonLibNaiveConnectivity.h delete mode 100644 C/inc/sonLibRandom.h delete mode 100644 C/inc/sonLibSet.h delete mode 100644 C/inc/sonLibSortedSet.h delete mode 100644 C/inc/sonLibString.h delete mode 100644 C/inc/sonLibTreap.h delete mode 100644 C/inc/sonLibTree.h delete mode 100644 C/inc/sonLibTuples.h delete mode 100644 C/inc/sonLibTypes.h delete mode 100644 C/inc/stGraph.h delete mode 100644 C/inc/stJson.h delete mode 100644 C/inc/stMatrix.h delete mode 100644 C/inc/stPhylogeny.h delete mode 100644 C/inc/stPosetAlignment.h delete mode 100644 C/inc/stSafeC.h delete mode 100644 C/inc/stSpimapLayer.h delete mode 100644 C/inc/stThreadPool.h delete mode 100644 C/inc/stUnionFind.h delete mode 100644 C/tests/allTests.c delete mode 100644 C/tests/cigarsTest.c delete mode 100644 C/tests/fastaCTest.c delete mode 100644 C/tests/kt_connect_test.cpp delete mode 100644 C/tests/kvDatabaseTest.c delete mode 100644 C/tests/kvDatabaseTestCommon.c delete mode 100644 C/tests/kvDatabaseTestCommon.h delete mode 100644 C/tests/sonLibAlignTest.c delete mode 100644 C/tests/sonLibCacheTest.c delete mode 100644 C/tests/sonLibCommonTest.c delete mode 100644 C/tests/sonLibCompressionTest.c delete mode 100644 C/tests/sonLibConnectivityTests.c delete mode 100644 C/tests/sonLibDoubleTuplesTest.c delete mode 100644 C/tests/sonLibEdgeContainerTests.c delete mode 100644 C/tests/sonLibEulerTest.c delete mode 100644 C/tests/sonLibExceptTest.c delete mode 100644 C/tests/sonLibFileTest.c delete mode 100644 C/tests/sonLibGlobalsTest.h delete mode 100644 C/tests/sonLibGraphTest.c delete mode 100644 C/tests/sonLibHashTest.c delete mode 100644 C/tests/sonLibIntTuplesTest.c delete mode 100644 C/tests/sonLibListTest.c delete mode 100644 C/tests/sonLibPosetAlignmentTest.c delete mode 100644 C/tests/sonLibRandomTest.c delete mode 100644 C/tests/sonLibSetTest.c delete mode 100644 C/tests/sonLibSortedSetTest.c delete mode 100644 C/tests/sonLibStringTest.c delete mode 100644 C/tests/sonLibTreapTest.c delete mode 100644 C/tests/sonLibTreeTest.c delete mode 100644 C/tests/sonLibTuplesTest.c delete mode 100644 C/tests/stMatrixTest.c delete mode 100644 C/tests/stPhylogenyTest.c delete mode 100644 C/tests/stThreadPoolTest.c delete mode 100644 C/tests/stUnionFindTest.c delete mode 100644 LICENSE.txt delete mode 100644 Makefile delete mode 100644 __init__.py delete mode 100644 allTests.py delete mode 100644 bioio.py delete mode 100644 bioioTest.py delete mode 100644 cigarsTest.py delete mode 100644 doc/INSTALL.txt delete mode 100644 doc/README delete mode 100644 doc/abbreviations.txt delete mode 100644 externalTools/Makefile delete mode 100644 externalTools/cutest/AllTests.c delete mode 100644 externalTools/cutest/CuTest.c delete mode 100644 externalTools/cutest/CuTest.h delete mode 100644 externalTools/cutest/CuTestTest.c delete mode 100644 externalTools/cutest/Makefile delete mode 100644 externalTools/cutest/README.txt delete mode 100644 externalTools/cutest/index.html delete mode 100644 externalTools/cutest/license.txt delete mode 100644 externalTools/cutest/make-tests.sh delete mode 100644 externalTools/cutest/style.css delete mode 100755 externalTools/quicktree_1.1/Makefile delete mode 100644 externalTools/quicktree_1.1/README delete mode 100644 externalTools/quicktree_1.1/bin/.gitignore delete mode 100644 externalTools/quicktree_1.1/include/align.h delete mode 100644 externalTools/quicktree_1.1/include/aln2dist.h delete mode 100644 externalTools/quicktree_1.1/include/aln2tree.h delete mode 100644 externalTools/quicktree_1.1/include/buildtree.h delete mode 100644 externalTools/quicktree_1.1/include/buildtree.h~ delete mode 100644 externalTools/quicktree_1.1/include/cluster.h delete mode 100644 externalTools/quicktree_1.1/include/dist2tree.h delete mode 100644 externalTools/quicktree_1.1/include/distancemat.h delete mode 100644 externalTools/quicktree_1.1/include/options.h delete mode 100644 externalTools/quicktree_1.1/include/sequence.h delete mode 100644 externalTools/quicktree_1.1/include/tree.h delete mode 100644 externalTools/quicktree_1.1/include/util.h delete mode 100644 externalTools/quicktree_1.1/obj/.gitignore delete mode 100644 externalTools/quicktree_1.1/src/align.c delete mode 100644 externalTools/quicktree_1.1/src/aln2dist.c delete mode 100644 externalTools/quicktree_1.1/src/aln2tree.c delete mode 100644 externalTools/quicktree_1.1/src/buildtree.c delete mode 100644 externalTools/quicktree_1.1/src/cluster.c delete mode 100644 externalTools/quicktree_1.1/src/dist2tree.c delete mode 100644 externalTools/quicktree_1.1/src/distancemat.c delete mode 100644 externalTools/quicktree_1.1/src/distancemat_merops.c delete mode 100644 externalTools/quicktree_1.1/src/options.c delete mode 100644 externalTools/quicktree_1.1/src/quicktree.c delete mode 100644 externalTools/quicktree_1.1/src/sequence.c delete mode 100644 externalTools/quicktree_1.1/src/tree.c delete mode 100755 externalTools/quicktree_1.1/src/util.c delete mode 100644 include.mk delete mode 100644 kvdbTest.py delete mode 100644 misc.py delete mode 100644 nxnewick.py delete mode 100644 nxnewickTest.py delete mode 100644 nxtree.py delete mode 100644 nxtreeTest.py delete mode 100755 setup.py delete mode 100644 sonLib_daemonize.py delete mode 100644 tree.py delete mode 100644 treeTest.py delete mode 100644 unitTest.py diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a741f6a..0000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -bin/* -lib/* -bin/ -lib/ -*.pyc -*.o -*.a diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29..0000000 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index de1b201..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -sudo: required -dist: trusty -language: c++ -before_install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y libtokyocabinet-dev libkyototycoon-dev kyototycoon libkyotocabinet-dev; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then rvm install ruby-2.3.3; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then rvm use 2.3.3; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install tokyo-cabinet kyoto-cabinet kyoto-tycoon; fi -script: - - make && PATH=$PATH:`pwd`/bin make test -os: - - linux - - osx -env: - - CGL_DEBUG=1 - - CGL_DEBUG=ultra -matrix: - exclude: - # The default OSX env doesn't have a version that supports - # -fsanitize=address. - - env: CGL_DEBUG=ultra - os: osx diff --git a/C/Makefile b/C/Makefile deleted file mode 100644 index cf83395..0000000 --- a/C/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -include ../include.mk -binPath = ../bin -libPath = ../lib - -libSources = impl/*.c -cppSources = impl/*.cpp -libHeaders = $(wildcard inc/*.h) -libInternalHeaders = impl/*.h -libTests = tests/sonLib*.c tests/st* -quickTreeObjects = ../externalTools/quicktree_1.1/obj/buildtree.o ../externalTools/quicktree_1.1/obj/cluster.o ../externalTools/quicktree_1.1/obj/distancemat.o ../externalTools/quicktree_1.1/obj/options.o ../externalTools/quicktree_1.1/obj/sequence.o ../externalTools/quicktree_1.1/obj/tree.o ../externalTools/quicktree_1.1/obj/util.o -quickTreeLibPath = ../externalTools/quicktree_1.1/include/ - -testProgs = ${binPath}/sonLibTests ${binPath}/sonLib_kvDatabaseTest ${binPath}/sonLib_cigarTest ${binPath}/sonLib_fastaCTest - -cflags += ${tokyoCabinetIncl} ${kyotoTycoonIncl} ${tokyoTyrantIncl} ${mysqlIncl} ${pgsqlIncl} -I${quickTreeLibPath} $(CFLAGS) -cppflags += ${kyotoTycoonIncl} - -all : ${libPath}/sonLib.a ${testProgs} - -clean : - rm -rf ${binPath} ${libPath} - -${binPath}/sonLibTests : ${libTests} ${libInternalHeaders} ${libPath}/sonLib.a ${libPath}/cuTest.a tests/allTests.c - @mkdir -p $(dir $@) - ${cxx} $(LDFLAGS) $(CPPFLAGS) ${cflags} -I inc -I ${libPath} -o $@.tmp tests/allTests.c ${libTests} ${libPath}/sonLib.a ${libPath}/cuTest.a ${dblibs} ${mysqlLibs} -lm -lstdc++ -lpthread - mv $@.tmp $@ - -${binPath}/sonLib_kvDatabaseTest : ${libTests} ${libInternalHeaders} ${libPath}/sonLib.a ${libPath}/cuTest.a tests/kvDatabaseTest.c tests/kvDatabaseTestCommon.c - @mkdir -p $(dir $@) - ${cxx} $(LDFLAGS) $(CPPFLAGS) ${cflags} -I inc -I ${libPath} -I tests -o $@.tmp tests/kvDatabaseTest.c tests/kvDatabaseTestCommon.c ${libPath}/sonLib.a ${libPath}/cuTest.a ${dblibs} ${mysqlLibs} -lm - mv $@.tmp $@ - -${binPath}/sonLib_cigarTest : tests/cigarsTest.c ${libTests} ${libInternalHeaders} ${libPath}/sonLib.a - @mkdir -p $(dir $@) - ${cxx} $(LDFLAGS) $(CPPFLAGS) ${cflags} -I inc -I ${libPath} -o $@.tmp tests/cigarsTest.c ${libPath}/sonLib.a -lm - mv $@.tmp $@ - -${binPath}/sonLib_fastaCTest : tests/fastaCTest.c ${libTests} ${libInternalHeaders} ${libPath}/sonLib.a - @mkdir -p $(dir $@) - ${cxx} $(LDFLAGS) $(CPPFLAGS) ${cflags} -I inc -I ${libPath} -o $@.tmp tests/fastaCTest.c ${libPath}/sonLib.a -lm - mv $@.tmp $@ - -${binPath}/kt_connect_test : tests/kt_connect_test.cpp ${libTests} ${libInternalHeaders} ${libPath}/sonLib.a - @mkdir -p $(dir $@) - ${cpp} $(LDFLAGS) $(CPPFLAGS) ${cppflags} -I inc -I ${libPath}/ -o $@.tmp tests/kt_connect_test.cpp ${libPath}/sonLib.a ${dblibs} -lm - mv $@.tmp $@ - -${libPath}/%.h: inc/%.h - @mkdir -p $(dir $@) - cp $< $@.tmp - mv $@.tmp $@ - -${libPath}/sonLib.a : ${libSources} ${cppSources} $(foreach l, ${libHeaders}, ${libPath}/$(notdir $l)) ${libInternalHeaders} - @mkdir -p $(dir $@) - ${cxx} $(CPPFLAGS) ${cflags} -I inc -I ${libPath}/ -c ${libSources} - ${cpp} $(CPPFLAGS) ${cppflags} -I inc -I ${libPath}/ -c ${cppSources} - ar rc sonLib.a *.o ${quickTreeObjects} - ranlib sonLib.a - rm *.o - mv sonLib.a ${libPath}/ - -test: - python allTests.py --testLength=SHORT --logLevel CRITICAL diff --git a/C/impl/avl.c b/C/impl/avl.c deleted file mode 100644 index cac9f06..0000000 --- a/C/impl/avl.c +++ /dev/null @@ -1,883 +0,0 @@ -/* Produced by texiweb from libavl.w. */ - -/* libavl - library for manipulation of binary trees. - Copyright (C) 1998-2002, 2004 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 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. - - The author may be contacted at on the Internet, or - write to Ben Pfaff, Stanford University, Computer Science Dept., 353 - Serra Mall, Stanford CA 94305, USA. - */ - -#include -#include -#include -#include -#include "avl.h" -#include "fastCMaths.h" -#include "sonLibGlobalsInternal.h" - -/* Creates and returns a new table - with comparison function |compare| using parameter |param| - and memory allocator |allocator|. - Returns |NULL| if memory allocation failed. */ -struct avl_table * -avl_create(avl_comparison_func *compare, void *param, - struct libavl_allocator *allocator) { - struct avl_table *tree; - - assert (compare != NULL); - - if (allocator == NULL) - allocator = &avl_allocator_default; - - tree = allocator->libavl_malloc(allocator, sizeof *tree); - assert(tree != NULL); - if (tree == NULL) - return NULL; - - tree->avl_root = NULL; - tree->avl_compare = compare; - tree->avl_param = param; - tree->avl_alloc = allocator; - tree->avl_count = 0; - tree->avl_generation = 0; - - return tree; -} - -/* Search |tree| for an item matching |item|, and return it if found. - Otherwise return |NULL|. */ -void * -avl_find(const struct avl_table *tree, const void *item) { - const struct avl_node *p; - - assert (tree != NULL && item != NULL); - for (p = tree->avl_root; p != NULL;) { - int32_t cmp = tree->avl_compare(item, p->avl_data, tree->avl_param); - - if (cmp < 0) - p = p->avl_link[0]; - else if (cmp > 0) - p = p->avl_link[1]; - else - /* |cmp == 0| */ - return p->avl_data; - } - - return NULL; -} - -/* Search in |tree| for the object minimally less than |item|, and return it if found. - Otherwise return |NULL| if no object less than |item| */ -void * -avl_find_lessThan(const struct avl_table *tree, const void *item) { - const struct avl_node *p; - - assert (tree != NULL && item != NULL); - void *lessThan = NULL; - for (p = tree->avl_root; p != NULL;) { - int32_t cmp = tree->avl_compare(item, p->avl_data, tree->avl_param); - - if (cmp <= 0) { - p = p->avl_link[0]; - } else { // cmp > 0 - lessThan = p->avl_data; - p = p->avl_link[1]; - } - } - - return lessThan; -} - -/* Search in |tree| for the object minimally less than |item|, and return it if found. - Otherwise return |NULL| if no object less than |item| */ -void * -avl_find_lessThanOrEqual(const struct avl_table *tree, const void *item) { - const struct avl_node *p; - - assert (tree != NULL && item != NULL); - void *lessThan = NULL; - for (p = tree->avl_root; p != NULL;) { - int32_t cmp = tree->avl_compare(item, p->avl_data, tree->avl_param); - - if (cmp < 0) { - p = p->avl_link[0]; - } else if(cmp > 0) { - lessThan = p->avl_data; - p = p->avl_link[1]; - } - else { - return p->avl_data; - } - } - - return lessThan; -} - -/* Search in |tree| for the object minimally greater than |item|, and return it if found. - Otherwise return |NULL|. */ -void * -avl_find_greaterThan(const struct avl_table *tree, const void *item) { - const struct avl_node *p; - - assert (tree != NULL && item != NULL); - void *greaterThan = NULL; - for (p = tree->avl_root; p != NULL;) { - int32_t cmp = tree->avl_compare(item, p->avl_data, tree->avl_param); - - if (cmp >= 0) { - p = p->avl_link[1]; - } else { // cmp < 0 - greaterThan = p->avl_data; - p = p->avl_link[0]; - } - } - - return greaterThan; -} - -/* Search in |tree| for the object equal or minimally greater than |item|, and return it if found. - Otherwise return |NULL|. */ -void * -avl_find_greaterThanOrEqual(const struct avl_table *tree, const void *item) { - const struct avl_node *p; - - assert (tree != NULL && item != NULL); - void *greaterThan = NULL; - for (p = tree->avl_root; p != NULL;) { - int32_t cmp = tree->avl_compare(item, p->avl_data, tree->avl_param); - - if (cmp > 0) { - p = p->avl_link[1]; - } else if(cmp < 0) { - greaterThan = p->avl_data; - p = p->avl_link[0]; - } - else { - return p->avl_data; - } - } - - return greaterThan; -} - -/* Inserts |item| INT_32o |tree| and returns a poINT_32er to |item|'s address. - If a duplicate item is found in the tree, - returns a poINT_32er to the duplicate without inserting |item|. - Returns |NULL| in case of memory allocation failure. */ -void ** -avl_probe(struct avl_table *tree, void *item) { - struct avl_node *y, *z; /* Top node to update balance factor, and parent. */ - struct avl_node *p, *q; /* Iterator, and parent. */ - struct avl_node *n; /* Newly inserted node. */ - struct avl_node *w; /* New root of rebalanced subtree. */ - int32_t dir; /* Direction to descend. */ - - unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */ - int32_t k = 0; /* Number of cached results. */ - - assert (tree != NULL && item != NULL); - - z = (struct avl_node *) &tree->avl_root; - y = tree->avl_root; - dir = 0; - for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir]) { - int32_t cmp = tree->avl_compare(item, p->avl_data, tree->avl_param); - if (cmp == 0) - return &p->avl_data; - - if (p->avl_balance != 0) - z = q, y = p, k = 0; - da[k++] = dir = cmp > 0; - } - - n = q->avl_link[dir] = tree->avl_alloc->libavl_malloc(tree->avl_alloc, - sizeof *n); - if (n == NULL) - return NULL; - - tree->avl_count++; - n->avl_data = item; - n->avl_link[0] = n->avl_link[1] = NULL; - n->avl_balance = 0; - if (y == NULL) - return &n->avl_data; - - for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++) - if (da[k] == 0) - p->avl_balance--; - else - p->avl_balance++; - - if (y->avl_balance == -2) { - struct avl_node *x = y->avl_link[0]; - if (x->avl_balance == -1) { - w = x; - y->avl_link[0] = x->avl_link[1]; - x->avl_link[1] = y; - x->avl_balance = y->avl_balance = 0; - } else { - assert (x->avl_balance == +1); - w = x->avl_link[1]; - x->avl_link[1] = w->avl_link[0]; - w->avl_link[0] = x; - y->avl_link[0] = w->avl_link[1]; - w->avl_link[1] = y; - if (w->avl_balance == -1) - x->avl_balance = 0, y->avl_balance = +1; - else if (w->avl_balance == 0) - x->avl_balance = y->avl_balance = 0; - else - /* |w->avl_balance == +1| */ - x->avl_balance = -1, y->avl_balance = 0; - w->avl_balance = 0; - } - } else if (y->avl_balance == +2) { - struct avl_node *x = y->avl_link[1]; - if (x->avl_balance == +1) { - w = x; - y->avl_link[1] = x->avl_link[0]; - x->avl_link[0] = y; - x->avl_balance = y->avl_balance = 0; - } else { - assert (x->avl_balance == -1); - w = x->avl_link[0]; - x->avl_link[0] = w->avl_link[1]; - w->avl_link[1] = x; - y->avl_link[1] = w->avl_link[0]; - w->avl_link[0] = y; - if (w->avl_balance == +1) - x->avl_balance = 0, y->avl_balance = -1; - else if (w->avl_balance == 0) - x->avl_balance = y->avl_balance = 0; - else - /* |w->avl_balance == -1| */ - x->avl_balance = +1, y->avl_balance = 0; - w->avl_balance = 0; - } - } else - return &n->avl_data; - z->avl_link[y != z->avl_link[0]] = w; - - tree->avl_generation++; - return &n->avl_data; -} - -/* Inserts |item| INT_32o |table|. - Returns |NULL| if |item| was successfully inserted - or if a memory allocation error occurred. - Otherwise, returns the duplicate item. */ -void * -avl_insert(struct avl_table *table, void *item) { - void **p = avl_probe(table, item); - return p == NULL || *p == item ? NULL : *p; -} - -/* Inserts |item| INT_32o |table|, replacing any duplicate item. - Returns |NULL| if |item| was inserted without replacing a duplicate, - or if a memory allocation error occurred. - Otherwise, returns the item that was replaced. */ -void * -avl_replace(struct avl_table *table, void *item) { - void **p = avl_probe(table, item); - if (p == NULL || *p == item) - return NULL; - else { - void *r = *p; - *p = item; - return r; - } -} - -/* Deletes from |tree| and returns an item matching |item|. - Returns a null poINT_32er if no matching item found. */ -void * -avl_delete(struct avl_table *tree, const void *item) { - /* Stack of nodes. */ - struct avl_node *pa[AVL_MAX_HEIGHT]; /* Nodes. */ - unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */ - int32_t k; /* Stack poINT_32er. */ - - struct avl_node *p; /* Traverses tree to find node to delete. */ - int32_t cmp; /* Result of comparison between |item| and |p|. */ - - assert (tree != NULL && item != NULL); - - k = 0; - p = (struct avl_node *) &tree->avl_root; - for (cmp = -1; cmp != 0; cmp = tree->avl_compare(item, p->avl_data, - tree->avl_param)) { - int32_t dir = cmp > 0; - - pa[k] = p; - da[k++] = dir; - - p = p->avl_link[dir]; - if (p == NULL) - return NULL; - } - item = p->avl_data; - - if (p->avl_link[1] == NULL) - pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0]; - else { - struct avl_node *r = p->avl_link[1]; - if (r->avl_link[0] == NULL) { - r->avl_link[0] = p->avl_link[0]; - r->avl_balance = p->avl_balance; - pa[k - 1]->avl_link[da[k - 1]] = r; - da[k] = 1; - pa[k++] = r; - } else { - struct avl_node *s; - int32_t j = k++; - - for (;;) { - da[k] = 0; - pa[k++] = r; - s = r->avl_link[0]; - if (s->avl_link[0] == NULL) - break; - - r = s; - } - - s->avl_link[0] = p->avl_link[0]; - r->avl_link[0] = s->avl_link[1]; - s->avl_link[1] = p->avl_link[1]; - s->avl_balance = p->avl_balance; - - pa[j - 1]->avl_link[da[j - 1]] = s; - da[j] = 1; - pa[j] = s; - } - } - - tree->avl_alloc->libavl_free(tree->avl_alloc, p); - - assert (k> 0); - while (--k > 0) { - struct avl_node *y = pa[k]; - - if (da[k] == 0) { - y->avl_balance++; - if (y->avl_balance == +1) - break; - else if (y->avl_balance == +2) { - struct avl_node *x = y->avl_link[1]; - if (x->avl_balance == -1) { - struct avl_node *w; - assert (x->avl_balance == -1); - w = x->avl_link[0]; - x->avl_link[0] = w->avl_link[1]; - w->avl_link[1] = x; - y->avl_link[1] = w->avl_link[0]; - w->avl_link[0] = y; - if (w->avl_balance == +1) - x->avl_balance = 0, y->avl_balance = -1; - else if (w->avl_balance == 0) - x->avl_balance = y->avl_balance = 0; - else - /* |w->avl_balance == -1| */ - x->avl_balance = +1, y->avl_balance = 0; - w->avl_balance = 0; - pa[k - 1]->avl_link[da[k - 1]] = w; - } else { - y->avl_link[1] = x->avl_link[0]; - x->avl_link[0] = y; - pa[k - 1]->avl_link[da[k - 1]] = x; - if (x->avl_balance == 0) { - x->avl_balance = -1; - y->avl_balance = +1; - break; - } else - x->avl_balance = y->avl_balance = 0; - } - } - } else { - y->avl_balance--; - if (y->avl_balance == -1) - break; - else if (y->avl_balance == -2) { - struct avl_node *x = y->avl_link[0]; - if (x->avl_balance == +1) { - struct avl_node *w; - assert (x->avl_balance == +1); - w = x->avl_link[1]; - x->avl_link[1] = w->avl_link[0]; - w->avl_link[0] = x; - y->avl_link[0] = w->avl_link[1]; - w->avl_link[1] = y; - if (w->avl_balance == -1) - x->avl_balance = 0, y->avl_balance = +1; - else if (w->avl_balance == 0) - x->avl_balance = y->avl_balance = 0; - else - /* |w->avl_balance == +1| */ - x->avl_balance = -1, y->avl_balance = 0; - w->avl_balance = 0; - pa[k - 1]->avl_link[da[k - 1]] = w; - } else { - y->avl_link[0] = x->avl_link[1]; - x->avl_link[1] = y; - pa[k - 1]->avl_link[da[k - 1]] = x; - if (x->avl_balance == 0) { - x->avl_balance = +1; - y->avl_balance = -1; - break; - } else - x->avl_balance = y->avl_balance = 0; - } - } - } - } - - tree->avl_count--; - tree->avl_generation++; - return (void *) item; -} - -/* Refreshes the stack of parent poINT_32ers in |trav| - and updates its generation number. */ -static void trav_refresh(struct avl_traverser *trav) { - assert (trav != NULL); - - trav->avl_generation = trav->avl_table->avl_generation; - - if (trav->avl_node != NULL) { - avl_comparison_func *cmp = trav->avl_table->avl_compare; - void *param = trav->avl_table->avl_param; - struct avl_node *node = trav->avl_node; - struct avl_node *i; - - trav->avl_height = 0; - for (i = trav->avl_table->avl_root; i != node;) { - assert (trav->avl_height < AVL_MAX_HEIGHT); - assert (i != NULL); - - trav->avl_stack[trav->avl_height++] = i; - i = i->avl_link[cmp(node->avl_data, i->avl_data, param) > 0]; - } - } -} - -/* Initializes |trav| for use with |tree| - and selects the null node. */ -void avl_t_init(struct avl_traverser *trav, struct avl_table *tree) { - trav->avl_table = tree; - trav->avl_node = NULL; - trav->avl_height = 0; - trav->avl_generation = tree->avl_generation; -} - -/* Initializes |trav| for |tree| - and selects and returns a poINT_32er to its least-valued item. - Returns |NULL| if |tree| contains no nodes. */ -void * -avl_t_first(struct avl_traverser *trav, struct avl_table *tree) { - struct avl_node *x; - - assert (tree != NULL && trav != NULL); - - trav->avl_table = tree; - trav->avl_height = 0; - trav->avl_generation = tree->avl_generation; - - x = tree->avl_root; - if (x != NULL) - while (x->avl_link[0] != NULL) { - assert (trav->avl_height < AVL_MAX_HEIGHT); - trav->avl_stack[trav->avl_height++] = x; - x = x->avl_link[0]; - } - trav->avl_node = x; - - return x != NULL ? x->avl_data : NULL; -} - -/* Initializes |trav| for |tree| - and selects and returns a poINT_32er to its greatest-valued item. - Returns |NULL| if |tree| contains no nodes. */ -void * -avl_t_last(struct avl_traverser *trav, struct avl_table *tree) { - struct avl_node *x; - - assert (tree != NULL && trav != NULL); - - trav->avl_table = tree; - trav->avl_height = 0; - trav->avl_generation = tree->avl_generation; - - x = tree->avl_root; - if (x != NULL) - while (x->avl_link[1] != NULL) { - assert (trav->avl_height < AVL_MAX_HEIGHT); - trav->avl_stack[trav->avl_height++] = x; - x = x->avl_link[1]; - } - trav->avl_node = x; - - return x != NULL ? x->avl_data : NULL; -} - -/* Searches for |item| in |tree|. - If found, initializes |trav| to the item found and returns the item - as well. - If there is no matching item, initializes |trav| to the null item - and returns |NULL|. */ -void * -avl_t_find(struct avl_traverser *trav, struct avl_table *tree, void *item) { - struct avl_node *p, *q; - - assert (trav != NULL && tree != NULL && item != NULL); - trav->avl_table = tree; - trav->avl_height = 0; - trav->avl_generation = tree->avl_generation; - for (p = tree->avl_root; p != NULL; p = q) { - int32_t cmp = tree->avl_compare(item, p->avl_data, tree->avl_param); - - if (cmp < 0) - q = p->avl_link[0]; - else if (cmp > 0) - q = p->avl_link[1]; - else /* |cmp == 0| */ - { - trav->avl_node = p; - return p->avl_data; - } - - assert (trav->avl_height < AVL_MAX_HEIGHT); - trav->avl_stack[trav->avl_height++] = p; - } - - trav->avl_height = 0; - trav->avl_node = NULL; - return NULL; -} - -/* Attempts to insert |item| INT_32o |tree|. - If |item| is inserted successfully, it is returned and |trav| is - initialized to its location. - If a duplicate is found, it is returned and |trav| is initialized to - its location. No replacement of the item occurs. - If a memory allocation failure occurs, |NULL| is returned and |trav| - is initialized to the null item. */ -void * -avl_t_insert(struct avl_traverser *trav, struct avl_table *tree, void *item) { - void **p; - - assert (trav != NULL && tree != NULL && item != NULL); - - p = avl_probe(tree, item); - if (p != NULL) { - trav->avl_table = tree;trav->avl_node = - ((struct avl_node *) - ((char *) p - offsetof (struct avl_node, avl_data))); - trav->avl_generation = tree->avl_generation - 1; - return *p; - } else { - avl_t_init(trav, tree); - return NULL; - } -} - -/* Initializes |trav| to have the same current node as |src|. */ -void * -avl_t_copy(struct avl_traverser *trav, const struct avl_traverser *src) { - assert (trav != NULL && src != NULL); - - if (trav != src) { - trav->avl_table = src->avl_table; - trav->avl_node = src->avl_node; - trav->avl_generation = src->avl_generation; - if (trav->avl_generation == trav->avl_table->avl_generation) { - trav->avl_height = src->avl_height; - memcpy(trav->avl_stack, (const void *) src->avl_stack, - sizeof *trav->avl_stack * trav->avl_height); - } - } - - return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL; -} - -/* Returns the next data item in inorder - within the tree being traversed with |trav|, - or if there are no more data items returns |NULL|. */ -void * -avl_t_next(struct avl_traverser *trav) { - struct avl_node *x; - - assert (trav != NULL); - - if (trav->avl_generation != trav->avl_table->avl_generation) - trav_refresh(trav); - - x = trav->avl_node; - if (x == NULL) { - return avl_t_first(trav, trav->avl_table); - } else if (x->avl_link[1] != NULL) { - assert (trav->avl_height < AVL_MAX_HEIGHT); - trav->avl_stack[trav->avl_height++] = x; - x = x->avl_link[1]; - - while (x->avl_link[0] != NULL) { - assert (trav->avl_height < AVL_MAX_HEIGHT); - trav->avl_stack[trav->avl_height++] = x; - x = x->avl_link[0]; - } - } else { - struct avl_node *y; - - do { - if (trav->avl_height == 0) { - trav->avl_node = NULL; - return NULL; - } - - y = x; - x = trav->avl_stack[--trav->avl_height]; - } while (y == x->avl_link[1]); - } - trav->avl_node = x; - - return x->avl_data; -} - -/* Returns the previous data item in inorder - within the tree being traversed with |trav|, - or if there are no more data items returns |NULL|. */ -void * -avl_t_prev(struct avl_traverser *trav) { - struct avl_node *x; - - assert (trav != NULL); - - if (trav->avl_generation != trav->avl_table->avl_generation) - trav_refresh(trav); - - x = trav->avl_node; - if (x == NULL) { - return avl_t_last(trav, trav->avl_table); - } else if (x->avl_link[0] != NULL) { - assert (trav->avl_height < AVL_MAX_HEIGHT); - trav->avl_stack[trav->avl_height++] = x; - x = x->avl_link[0]; - - while (x->avl_link[1] != NULL) { - assert (trav->avl_height < AVL_MAX_HEIGHT); - trav->avl_stack[trav->avl_height++] = x; - x = x->avl_link[1]; - } - } else { - struct avl_node *y; - - do { - if (trav->avl_height == 0) { - trav->avl_node = NULL; - return NULL; - } - - y = x; - x = trav->avl_stack[--trav->avl_height]; - } while (y == x->avl_link[0]); - } - trav->avl_node = x; - - return x->avl_data; -} - -/* Returns |trav|'s current item. */ -void * -avl_t_cur(struct avl_traverser *trav) { - assert (trav != NULL); - - return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL; -} - -/* Replaces the current item in |trav| by |new| and returns the item replaced. - |trav| must not have the null item selected. - The new item must not upset the ordering of the tree. */ -void * -avl_t_replace(struct avl_traverser *trav, void *new) { - void *old; - - assert (trav != NULL && trav->avl_node != NULL && new != NULL); - old = trav->avl_node->avl_data; - trav->avl_node->avl_data = new; - return old; -} - -/* Destroys |new| with |avl_destroy (new, destroy)|, - first setting right links of nodes in |stack| within |new| - to null poINT_32ers to avoid touching uninitialized data. */ -static void copy_error_recovery(struct avl_node **stack, int32_t height, - struct avl_table *new, avl_item_func *destroy) { - assert (stack != NULL && height >= 0 && new != NULL); - - for (; height > 2; height -= 2) - stack[height - 1]->avl_link[1] = NULL; - avl_destroy(new, destroy); -} - -/* Copies |org| to a newly created tree, which is returned. - If |copy != NULL|, each data item in |org| is first passed to |copy|, - and the return values are inserted INT_32o the tree, - with |NULL| return values taken as indications of failure. - On failure, destroys the partially created new tree, - applying |destroy|, if non-null, to each item in the new tree so far, - and returns |NULL|. - If |allocator != NULL|, it is used for allocation in the new tree. - Otherwise, the same allocator used for |org| is used. */ -struct avl_table * -avl_copy(const struct avl_table *org, avl_copy_func *copy, - avl_item_func *destroy, struct libavl_allocator *allocator) { - struct avl_node *stack[2 * (AVL_MAX_HEIGHT + 1)]; - int32_t height = 0; - - struct avl_table *new; - const struct avl_node *x; - struct avl_node *y; - - assert (org != NULL); - new = avl_create(org->avl_compare, org->avl_param, - allocator != NULL ? allocator : org->avl_alloc); - if (new == NULL) - return NULL; - new->avl_count = org->avl_count; - if (new->avl_count == 0) - return new; - - x = (const struct avl_node *) &org->avl_root; - y = (struct avl_node *) &new->avl_root; - for (;;) { - while (x->avl_link[0] != NULL) { - assert (height < 2 * (AVL_MAX_HEIGHT + 1)); - - y->avl_link[0] = new->avl_alloc->libavl_malloc(new->avl_alloc, - sizeof *y->avl_link[0]); - if (y->avl_link[0] == NULL) { - if (y != (struct avl_node *) &new->avl_root) { - y->avl_data = NULL; - y->avl_link[1] = NULL; - } - - copy_error_recovery(stack, height, new, destroy); - return NULL; - } - - stack[height++] = (struct avl_node *) x; - stack[height++] = y; - x = x->avl_link[0]; - y = y->avl_link[0]; - } - y->avl_link[0] = NULL; - - for (;;) { - y->avl_balance = x->avl_balance; - if (copy == NULL) - y->avl_data = x->avl_data; - else { - y->avl_data = copy(x->avl_data, org->avl_param); - if (y->avl_data == NULL) { - y->avl_link[1] = NULL; - copy_error_recovery(stack, height, new, destroy); - return NULL; - } - } - - if (x->avl_link[1] != NULL) { - y->avl_link[1] = new->avl_alloc->libavl_malloc(new->avl_alloc, - sizeof *y->avl_link[1]); - if (y->avl_link[1] == NULL) { - copy_error_recovery(stack, height, new, destroy); - return NULL; - } - - x = x->avl_link[1]; - y = y->avl_link[1]; - break; - } else - y->avl_link[1] = NULL; - - if (height <= 2) - return new; - - y = stack[--height]; - x = stack[--height]; - } - } - return 0; -} - -/* Frees storage allocated for |tree|. - If |destroy != NULL|, applies it to each data item in inorder. */ -void avl_destroy(struct avl_table *tree, avl_item_func *destroy) { - struct avl_node *p, *q; - - assert (tree != NULL); - - for (p = tree->avl_root; p != NULL; p = q) - if (p->avl_link[0] == NULL) { - q = p->avl_link[1]; - if (destroy != NULL && p->avl_data != NULL) - destroy(p->avl_data, tree->avl_param); - tree->avl_alloc->libavl_free(tree->avl_alloc, p); - } else { - q = p->avl_link[0]; - p->avl_link[0] = q->avl_link[1]; - q->avl_link[1] = p; - } - - tree->avl_alloc->libavl_free(tree->avl_alloc, tree); -} - -/* Allocates |size| bytes of space using |malloc()|. - Returns a null poINT_32er if allocation fails. */ -void * -avl_malloc(struct libavl_allocator *allocator, size_t size) { - assert (allocator != NULL && size> 0); - return st_malloc(size); -} - -/* Frees |block|. */ -void avl_free(struct libavl_allocator *allocator, void *block) { - assert (allocator != NULL && block != NULL); - free(block); -} - -/* Default memory allocator that uses |malloc()| and |free()|. */ -struct libavl_allocator avl_allocator_default = { avl_malloc, avl_free }; - -#undef NDEBUG -#include - -/* Asserts that |avl_insert()| succeeds at inserting |item| INT_32o |table|. */ -void( avl_assert_insert)(struct avl_table *table, void *item) { - void **p = avl_probe(table, item); - assert (p != NULL && *p == item); -} - -/* Asserts that |avl_delete()| really removes |item| from |table|, - and returns the removed item. */ -void * -( avl_assert_delete)(struct avl_table *table, void *item) { - void *p = avl_delete(table, item); - assert (p != NULL); - return p; -} - diff --git a/C/impl/bioioC.c b/C/impl/bioioC.c deleted file mode 100644 index 941ea38..0000000 --- a/C/impl/bioioC.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include -#include -#include -#include - -#include "fastCMaths.h" -#include "commonC.h" -#include "ctype.h" -#include "bioioC.h" - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//integer reader / writer -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -void readIntegers(FILE *file, int64_t intNumber, int64_t *iA) { - int64_t i; - - for(i=0; i%s\n", header); - int64_t lineLength = 100; - char line[lineLength+1]; - int64_t k = strlen(sequence); - for(int64_t i=0; i k ? k-i : lineLength; - memcpy(line, sequence+i, sizeof(char)*l); - line[l] = '\0'; - for(int64_t m=0; m') { //fasta start - fastaStart: - cA[0] = '\0'; - l = 0; - while(TRUE) { - j = getc(fastaFile); - if(j == EOF) { - seq = addSeqToList(seq, &k, &seqLength, cA, addSeq); //lax qualification for a sequence - return; - } - if(j == '\n') { - break; - } - //add to name string - cA[l++] = j; - cA[l] = '\0'; - } - while(TRUE) { //start of sequence - j = getc(fastaFile); - if(j == EOF) { - seq = addSeqToList(seq, &k, &seqLength, cA, addSeq); - return; - } - if(j != '\n' && j != ' ' && j != '\t') { - if(j == '>') { - //end of seq - seq = addSeqToList(seq, &k, &seqLength, cA, addSeq); - goto fastaStart; - } - else { //valid char - if(!isalpha(j) && j != '-') { - //For safety and sanity I only allows roman alphabet characters and gaps in fasta sequences. - st_errAbort("!!Got an unexpected character in input fasta sequence: '%c' \n", j); - } - seq = arrayPrepareAppend(seq, &seqLength, k+1, sizeof(char)); - seq[k++] = j; - } - } - } - } - } -} - -struct List *fastaRead_fastaNames; -struct List *fastaRead_seqs; -struct List *fastaRead_seqLengths; - -void fastaRead_function(const char *fastaHeader, const char *sequence, int64_t length) { - listAppend(fastaRead_fastaNames, stString_copy(fastaHeader)); - listAppend(fastaRead_seqs, stString_copy(sequence)); - listAppend(fastaRead_seqLengths, constructInt(length)); -} - -void fastaRead(FILE *fastaFile, struct List *seqs, struct List *seqLengths, struct List *fastaNames) { - fastaRead_fastaNames = fastaNames; - fastaRead_seqs = seqs; - fastaRead_seqLengths = seqLengths; - fastaReadToFunction(fastaFile, fastaRead_function); -} - -static stHash *fastaRead_map; - -void fastaRead_readToMapFunction(const char *fastaHeader, const char *sequence, int64_t length) { - stHash_insert(fastaRead_map, stString_copy(fastaHeader), stString_copy(sequence)); -} - -stHash *fastaReadToMap(FILE *fastaFile) { - fastaRead_map = stHash_construct3(stHash_stringKey, stHash_stringEqualKey, free, free); - - fastaReadToFunction(fastaFile, fastaRead_readToMapFunction); - - return fastaRead_map; -} - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//useful scanf functions -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - - -char *eatWhiteSpace(char *string) { - while(*string != '\0' && isspace(*string)) { - string++; - } - return string; -} - -int64_t parseInt(char **string, int64_t *j) { - /* - * Parses a string from the input string, and moves up the pointer. - * Returns 1 for success, 0 for failures, no action on the pointer occurs if failed. - */ - int64_t i; - - i = sscanf(*string, INT_STRING, j); - if(i == 1) { - *string = eatWhiteSpace(*string); - while(*string != '\0' && !isspace(**string)) { - (*string)++; - } - *string = eatWhiteSpace(*string); - return 1; - } - else { - return 0; - } -} - -int64_t parseFloat(char **string, float *j) { - /* - * Parses a string from the input string, and moves up the pointer. - * Returns 1 for success, 0 for failures, no action on the pointer occurs if failed. - */ - int64_t i; - - i = sscanf(*string, "%f", j); - if(i == 1) { - *string = eatWhiteSpace(*string); - while(*string != '\0' && !isspace(**string)) { - (*string)++; - } - *string = eatWhiteSpace(*string); - return 1; - } - else { - return 0; - } -} - -int64_t parseString(char **string, char *cA) { - /* - * Parses a string from the input string, and moves up the pointer. - * Returns 1 for success, 0 for failures, no action on the pointer occurs if failed. - */ - int64_t i; - - i = sscanf(*string, "%s", cA); - if(i == 1) { - *string = eatWhiteSpace(*string); - while(*string != '\0' && !isspace(**string)) { - (*string)++; - } - *string = eatWhiteSpace(*string); - return 1; - } - else { - return 0; - } -} - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//newick tree parser -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - - -char* eatString(char *string, char **newString) { - char *i; - - i = string; - while(*string != '\0' && !isspace(*string)) { - string++; - } - (*newString) = memcpy(st_malloc((string-i + 1)*sizeof(char)), i, (string-i)*sizeof(char)); - (*newString)[string - i] = '\0'; - return eatWhiteSpace(string); -} - -char *replaceString(char *oldString, char old, char *new, int64_t newLength) { - char *i; - int64_t j; - char *k; - char *newString; - j=0; - k=oldString; - for(i=oldString; *i != '\0'; i++) { - if(*i == old) { - j++; - } - } - newString = st_malloc(sizeof(char)*(j*(newLength-1) + (i-k) + 1)); - k=newString; - for(i=oldString; *i != '\0'; i++) { - if(*i == old) { - for(j=0; jlabel); - newickTreeString = newickTreeParser_getLabel(newickTreeString, &temp1->label); - f = defaultDistance; - newickTreeString = newickTreeParser_fn(newickTreeString, &f); - temp1->distance += f; - (*binaryTree) = temp1; - assert(*newickTreeString == ',' || *newickTreeString == ';' || *newickTreeString == ')' || *newickTreeString == '\0'); - - return newickTreeString; -} - -struct BinaryTree *newickTreeParser(char *newickTreeString, float defaultDistance, int64_t unaryNodes) { - struct BinaryTree *binaryTree; - char *i; - //lax newick tree parser - newickTreeString = replaceString(newickTreeString, '(', " ( ", 3); - newickTreeString = replaceAndFreeString(newickTreeString, ')', " ) ", 3); - newickTreeString = replaceAndFreeString(newickTreeString, ':', " : ", 3); - newickTreeString = replaceAndFreeString(newickTreeString, ',', " , ", 3); - newickTreeString = replaceAndFreeString(newickTreeString, ';', " ; ", 3); - i = newickTreeString; - newickTreeString = eatWhiteSpace(newickTreeString); - newickTreeParser_fn2(newickTreeString, defaultDistance, &binaryTree, unaryNodes); - free(i); - - return binaryTree; -} - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//read in fasta file, and turn into a column alignment -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -struct CharColumnAlignment *multiFastaRead(char *fastaFile) { - struct List *seqs; - struct List *seqLengths; - struct List *fastaNames; - FILE *fileHandle; - int64_t alignmentLength = 0; - struct CharColumnAlignment *charColumnAlignment; - int64_t i; - int64_t j; - int64_t k; - - seqs = constructEmptyList(0, free); - seqLengths = constructEmptyList(0, free); - fastaNames = constructEmptyList(0, free); - fileHandle = fopen(fastaFile, "r"); - fastaRead(fileHandle, seqs, seqLengths, fastaNames); - fclose(fileHandle); - - alignmentLength = 0; - if(seqLengths->length != 0) { - alignmentLength = listGetInt(seqLengths, 0); - } - for(i=0; ilength; i++) { - assert(alignmentLength == listGetInt(seqLengths, 0)); - } - charColumnAlignment = st_malloc(sizeof(struct CharColumnAlignment)); - charColumnAlignment->columnNo = alignmentLength; - charColumnAlignment->seqNo = seqLengths->length; - charColumnAlignment->columnAlignment = st_malloc(sizeof(char)*(charColumnAlignment->columnNo)*(charColumnAlignment->seqNo)); - k=0; - for(i=0; ilength; j++) { - charColumnAlignment->columnAlignment[k++] = ((char *)seqs->list[j])[i]; - } - } - destructList(seqs); - destructList(seqLengths); - destructList(fastaNames); - return charColumnAlignment; -} - -char *charColumnAlignment_getColumn(struct CharColumnAlignment *charColumnAlignment, int64_t col) { - return &charColumnAlignment->columnAlignment[col*charColumnAlignment->seqNo]; -} - -void destructCharColumnAlignment(struct CharColumnAlignment *charColumnAlignment) { - free(charColumnAlignment->columnAlignment); - free(charColumnAlignment); -} - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//Get line function, while getline is not standard. -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -int64_t benLine(char **s, int64_t *n, FILE *f) { - register int64_t nMinus1= ((*n)-1), i= 0; - - char *s2 = *s; - while(TRUE) { - register int64_t ch = (char)getc(f); - - if(ch == '\r') { - ch= getc(f); - } - - if(i == nMinus1) { - *n = 2*(*n) + 1; - *s = realloc(*s, (*n + 1)*sizeof(char)); - assert(*s != NULL); - s2 = *s + i; - nMinus1 = ((*n)-1); - } - - if((ch == '\n') || (ch == EOF)) { - *s2 = '\0'; - return(feof(f) ? -1 : i); - } - else { - *s2 = ch; - s2++; - } - ++i; - } - return 0; -} diff --git a/C/impl/commonC.c b/C/impl/commonC.c deleted file mode 100644 index 30044a2..0000000 --- a/C/impl/commonC.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "fastCMaths.h" -#include "commonC.h" -#include "hashTableC.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include // per IEEE Std 1003.1, 2004 -#include // for "legacy" systems -#include -#include - -void exitOnFailure(int64_t exitValue, const char *failureMessage, ...) { - if (exitValue != 0) { - va_list ap; - va_start(ap, failureMessage); - vfprintf(stderr, failureMessage, ap); - //vfprintf(stdout, string, ap); - va_end(ap); - exit(1); - } -} - -struct Chunks *constructChunks(int64_t chunkSize, int64_t elementSize) { - struct Chunks *chunks; - - chunks = st_malloc(sizeof(struct Chunks)); - chunks->chunkList = constructEmptyList(0, free); - chunks->remaining = 0; - chunks->chunkSize = chunkSize; - chunks->elementSize = elementSize; - return chunks; -} - -void destructChunks(struct Chunks *chunk) { - destructList(chunk->chunkList); - free(chunk); -} - -void *mallocChunk(struct Chunks *chunk) { - if (chunk->remaining-- > 0) { - return (chunk->chunk += chunk->elementSize); - } else { - chunk->chunk = st_malloc(chunk->elementSize * chunk->chunkSize); - listAppend(chunk->chunkList, chunk->chunk); - chunk->remaining = chunk->chunkSize - 1; - return chunk->chunk; - } -} - -void *arrayResize_NoCheck(void *current, int64_t *currentSize, int64_t newSize, - int64_t base) { - assert(*currentSize <= newSize); - if (current != NULL) { - free(current); - } - *currentSize = newSize; - return st_malloc(base * ((int64_t) newSize)); -} - -void *arrayResize(void *current, int64_t *currentSize, int64_t newSize, - int64_t base) { - if (*currentSize < newSize) { - return arrayResize_NoCheck(current, currentSize, newSize, base); - } - return current; -} - -void listResize(struct List *list, int64_t newMaxSize) { - list->list = arrayResize(list->list, &list->maxLength, newMaxSize, - sizeof(void *)); -} - -void *arrayCopyResize_NoCheck(void *current, int64_t *currentSize, - int64_t newSize, int64_t base) { - assert(*currentSize <= newSize); - void *new; - new = memcpy(st_malloc(((int64_t) base) * newSize), current, - ((int64_t) base) * (*currentSize)); - if (current != NULL) { - free(current); - } - *currentSize = newSize; - return new; -} - -void *arrayCopyResize(void *current, int64_t *currentSize, int64_t newSize, - int64_t base) { - if (*currentSize < newSize) { - return arrayCopyResize_NoCheck(current, currentSize, newSize, base); - } - return current; -} - -void *arrayPrepareAppend(void *current, int64_t *maxLength, int64_t newLength, - int64_t base) { - if (newLength >= *maxLength) { - return arrayCopyResize_NoCheck(current, maxLength, - (*maxLength) * 2 + newLength + SMALL_CHUNK_SIZE, base); - } - return current; -} - -void listReverse(struct List *list) { - int64_t i; - void *j; - int64_t k; - - k = list->length - 1; - for (i = 0; i < list->length / 2; i++) { - j = list->list[i]; - list->list[i] = list->list[k - i]; - list->list[k - i] = j; - } -} - -void listIntersection(struct List *list, struct List *list2, struct List *list3) { - //currently quadratic time, watch cost closely - //output list can be the same as the input list - int64_t i; - int64_t j; - int64_t k; - static void **scratch; - static int64_t scratchSize; - scratch = arrayResize(scratch, &scratchSize, list->length + 1, - sizeof(void *)); - k = 0; - for (i = 0; i < list->length; i++) { - for (j = 0; j < list2->length; j++) { - if (list->list[i] == list2->list[j]) { - scratch[k++] = list->list[i]; - break; - } - } - } - list3->length = 0; - for (i = 0; i < k; i++) { - listAppend(list3, scratch[i]); - } -} - -void listCopyResize(struct List *list, int64_t newMaxSize) { - list->list = arrayCopyResize(list->list, &list->maxLength, newMaxSize, - sizeof(void *)); -} - -struct hashtable *intListToHash(struct List *list, int64_t *(*getKey)(void *)) { - int64_t i; - void *key; - struct hashtable *hT; - - hT = create_hashtable(list->length, hashtable_intHashKey, - hashtable_intEqualKey, NULL, NULL); - for (i = 0; i < list->length; i++) { - key = getKey(list->list[i]); - hashtable_insert(hT, key, list->list[i]); - } - return hT; -} - -void swapListFields(struct List *list1, struct List *list2) { - assert(list1 != list2); - assert(list1->list == NULL || list1->list != list2->list); - void **list; - int64_t length; - int64_t maxLength; - - list = list1->list; - length = list1->length; - maxLength = list1->maxLength; - - list1->list = list2->list; - list1->length = list2->length; - list1->maxLength = list2->maxLength; - - list2->list = list; - list2->length = length; - list2->maxLength = maxLength; -} - -struct List *cloneList(struct List *source) { - struct List *to; - int64_t i; - - to = constructEmptyList(0, source->destructElement); - for (i = 0; i < source->length; i++) { - listAppend(to, source->list[i]); - } - return to; -} - -struct List *listCopy(struct List *list) { - struct List *list2; - int64_t i; - - list2 = constructEmptyList(0, list->destructElement); - for (i = 0; i < list->length; i++) { - listAppend(list2, list->list[i]); - } - return list2; -} - -void copyList(struct List *from, struct List *to) { - int64_t i; - - to->length = 0; - for (i = 0; i < from->length; i++) { - listAppend(to, from->list[i]); - } - - /*assert(from != to); - assert(from->list == NULL || from->list != to->list); - if(from->length > to->maxLength) { - listResize(to, from->length); - } - to->length = from->length; - to->list = memcpy(to->list, from->list, sizeof(void *)*from->length);*/ -} - -void listAppend(struct List *list, void *item) { - if (list->length >= list->maxLength) { - list->list = arrayCopyResize_NoCheck(list->list, &list->maxLength, - list->maxLength * 2 + TINY_CHUNK_SIZE, sizeof(void *)); - } - list->list[list->length++] = item; -} - -void *listRemoveFirst(struct List *list) { - int64_t i; - void *j; - - j = list->list[0]; - for (i = 1; i < list->length; i++) { - list->list[i - 1] = list->list[i]; - } - list->length--; - return j; -} - -void listAppendArray(struct List *list, void **array, int64_t length) { - int64_t i; - - if (list->length + length > list->maxLength) { - list->list = arrayCopyResize_NoCheck(list->list, &list->maxLength, - list->maxLength * 2 + length + TINY_CHUNK_SIZE, sizeof(void *)); - } - for (i = 0; i < length; i++) { - list->list[list->length++] = array[i]; - } -} - -int64_t listContains(struct List *list, void *k) { - int64_t i; - - for (i = 0; i < list->length; i++) { - if (list->list[i] == k) { - return TRUE; - } - } - return FALSE; -} - -int64_t listGetInt(struct List *list, int64_t index) { - assert(list != NULL); - assert(index >= 0); - assert(index < list->length); - return *((int64_t *) list->list[index]); -} - -float listGetFloat(struct List *list, int64_t index) { - assert(list != NULL); - assert(index >= 0); - assert(index < list->length); - return *((float *) list->list[index]); -} - -void listRemove(struct List *list, void *k) { - int64_t i, j; - for (i = 0; i < list->length; i++) { - if (list->list[i] == k) { - for (j = i + 1; j < list->length; j++) { - list->list[j - 1] = list->list[j]; - } - list->length--; - } - } -} - -struct List *lRD_list2 = NULL; - -void listRemoveDuplicates(struct List *list) { - int64_t i; - void *k; - - if (lRD_list2 == NULL) { - lRD_list2 = constructEmptyList(0, NULL); - } - lRD_list2->length = 0; - - for (i = 0; i < list->length; i++) { - k = list->list[i]; - if (listContains(lRD_list2, k) == FALSE) { - listAppend(lRD_list2, k); - } - } - - for (i = 0; i < lRD_list2->length; i++) { - list->list[i] = lRD_list2->list[i]; - } - list->length = lRD_list2->length; -} - -int64_t listContainsDuplicates(struct List *list) { - int64_t i, j; - void *k, *l; - - for (i = 0; i < list->length; i++) { - k = list->list[i]; - for (j = i + 1; j < list->length; j++) { - l = list->list[j]; - if (k == l) { - return TRUE; - } - } - } - return FALSE; -} - -//list functions -struct List *copyConstructList(void **list, int64_t length, - void(*destructElement)(void *)) { - struct List *i; - int64_t j; - - i = st_malloc(sizeof(struct List)); - i->length = length; - i->maxLength = length; - j = sizeof(void *) * length; - i->list = st_malloc(j); - memcpy(i->list, list, j); - i->destructElement = destructElement; - return i; -} - -struct List *constructZeroLengthList(int64_t length, - void(*destructElement)(void *)) { - struct List *l; - l = constructEmptyList(length, destructElement); - l->length = 0; - return l; -} - -struct List *constructEmptyList(int64_t length, void(*destructElement)(void *)) { - struct List *i; - - i = st_malloc(sizeof(struct List)); - i->length = length; - i->maxLength = length; - i->list = st_malloc(sizeof(void *) * length); - i->destructElement = destructElement; - return i; -} - -void destructList(struct List *list) { - int64_t i; - - if (list->destructElement != NULL) { - for (i = 0; i < list->length; i++) { //only free up to known area of list - list->destructElement(list->list[i]); - } - } - free(list->list); - free(list); -} - -int64_t *constructChunkInt(int64_t intValue, struct Chunks *chunks) { - int64_t *i; - - i = mallocChunk(chunks); - *i = intValue; - return i; -} - -int64_t *constructChunkLong(int64_t longValue, struct Chunks *chunks) { - int64_t *i; - - i = mallocChunk(chunks); - *i = longValue; - return i; -} - -//int lists - -struct IntList *constructEmptyIntList(int64_t length) { - struct IntList *intList; - - intList = st_malloc(sizeof(struct IntList)); - intList->length = length; - intList->maxLength = length; - intList->list = st_malloc(sizeof(int64_t) * length); - - return intList; -} - -void destructIntList(struct IntList *intList) { - free(intList->list); - free(intList); -} - -struct IntList *intListCopy(struct IntList *intList) { - int64_t i; - struct IntList *intList2 = constructEmptyIntList(intList->length); - assert(intList->length == intList2->length); - for (i = 0; i < intList->length; i++) { - intList2->list[i] = intList->list[i]; - } - return intList2; -} - -void intListAppend(struct IntList *list, int64_t item) { - if (list->length >= list->maxLength) { - list->list = arrayCopyResize_NoCheck(list->list, &list->maxLength, - list->maxLength * 2 + TINY_CHUNK_SIZE, sizeof(int64_t)); - } - list->list[list->length++] = item; -} - -//ints -float *constructFloat(float i) { - float *j; - - j = st_malloc(sizeof(float)); - *j = i; - return j; -} - -void destructFloat(float *i) { - free(i); -} - -int64_t *constructInt(int64_t i) { - int64_t *j; - - j = st_malloc(sizeof(int64_t)); - *j = i; - return j; -} - -void destructInt(int64_t *i) { - free(i); -} - -uint64_t hashtable_intPairHashKey(const void *k) { - const int64_t *iA; - iA = k; - return iA[0] + iA[1]; -} - -int hashtable_intPairEqualKey(const void *key1, const void *key2) { - const int64_t *iA; - const int64_t *iA2; - iA = key1; - iA2 = key2; - return (iA[0] == iA2[0] && iA[1] == iA2[1]) || (iA[0] == iA2[1] && iA[1] - == iA2[0]); -} - -uint64_t hashtable_orderedIntPairHashKey(const void *k) { - const int64_t *iA; - iA = k; - return iA[0]; -} - -int hashtable_orderedIntPairEqualKey(const void *key1, const void *key2) { - const int64_t *iA; - const int64_t *iA2; - iA = key1; - iA2 = key2; - return iA[0] == iA2[0] && iA[1] == iA2[1]; -} - -int64_t *constructIntPair(int64_t i, int64_t j) { - int64_t *k; - - k = st_malloc(sizeof(int64_t) * 2); - k[0] = i; - k[1] = j; - return k; -} - -void destructIntPair(int64_t *i) { - free(i); -} - -//ints -int64_t *constructLong(int64_t i) { - int64_t *j; - - j = st_malloc(sizeof(int64_t)); - *j = i; - return j; -} - -void destructLong(int64_t *i) { - free(i); -} - -/*uint64_t hashtable_stringHashKey( const void *k ) { - uint64_t i, j; - const char *cA; - - cA = k; - j = 0; - for(i=0; i *j ? 1 : 0; -} - -int64_t longComparator(int64_t *i, int64_t *j) { - return *i < *j ? -1 : *i > *j ? 1 : 0; -} - -int intComparator_Int(int64_t *i, int64_t *j) { - return *i < *j ? -1 : *i > *j ? 1 : 0; -} - -int longComparator_Int(int64_t *i, int64_t *j) { - return *i < *j ? -1 : *i > *j ? 1 : 0; -} - -int floatComparator(float **f, float **f2) { - return **f > **f2 ? 1 : (**f < **f2 ? -1 : 0); -} - -int64_t intsComparator(int64_t *ints1, int64_t *ints2, int64_t length) { - int64_t i; - int64_t j; - int64_t k; - - //assertLocal INT_32s1->length == INT_32s2->length; - if (ints1 == ints2) { - return 0; - } - - for (i = 0; i < length; ++i) { - j = ints1[i]; - k = ints2[i]; - if (j < k) { - return -1; - } - if (j > k) { - return 1; - } - } - return 0; -} - -struct TraversalID *constructTraversalID(int64_t midStart, int64_t mid, - int64_t midEnd, int64_t leafNo) { - struct TraversalID *traversalID; - - traversalID = st_malloc(sizeof(struct TraversalID)); - traversalID->midStart = midStart; - traversalID->mid = mid; - traversalID->midEnd = midEnd; - traversalID->leafNo = leafNo; - return traversalID; -} - -void destructTraversalID(struct TraversalID *traversalID) { - free(traversalID); -} - -struct BinaryTree *constructBinaryTree(float distance, int64_t internal, - const char *label, struct BinaryTree *left, struct BinaryTree *right) { - struct BinaryTree *binaryTree; - - binaryTree = st_malloc(sizeof(struct BinaryTree)); - binaryTree->distance = distance; - binaryTree->internal = internal; - binaryTree->label = stString_copy(label); - binaryTree->left = left; - binaryTree->right = right; - binaryTree->traversalID = NULL; - return binaryTree; -} - -void destructBinaryTree(struct BinaryTree *binaryTree) { - if (binaryTree->traversalID != NULL) { - destructTraversalID(binaryTree->traversalID); - } - if (binaryTree->left != NULL) { - destructBinaryTree(binaryTree->left); - } - if (binaryTree->right != NULL) { - destructBinaryTree(binaryTree->right); - } - free(binaryTree->label); - free(binaryTree); -} - -int64_t leftMostLeafNo(struct TraversalID *traversalID) { - return traversalID->midStart / 2; -} - -int64_t rightMostLeafNo(struct TraversalID *traversalID) { - return traversalID->midEnd / 2; -} - -int64_t leafNoInSubtree(struct TraversalID *traversalID) { - return rightMostLeafNo(traversalID) - leftMostLeafNo(traversalID) + 1; -} - -static void binaryTree_depthFirstNumbers_Traverse( - struct BinaryTree *binaryTree, int64_t *mid, int64_t *leafNo) { - int64_t i; - int64_t j; - - if (binaryTree->internal) { - //_isInternal(binaryTree): - i = *mid; - binaryTree_depthFirstNumbers_Traverse(binaryTree->left, mid, leafNo); - j = (*mid)++; - binaryTree_depthFirstNumbers_Traverse(binaryTree->right, mid, leafNo); - binaryTree->traversalID = constructTraversalID(i, j, *mid, INT64_MAX); - } else { - i = (*mid)++; - binaryTree->traversalID = constructTraversalID(i, i, *mid, (*leafNo)++); - } -} - -void binaryTree_getOrderedLeafStringsP(struct BinaryTree *binaryTree, - struct List *leafStrings) { - if (binaryTree->internal) { - binaryTree_getOrderedLeafStringsP(binaryTree->left, leafStrings); - binaryTree_getOrderedLeafStringsP(binaryTree->right, leafStrings); - } else { - listAppend(leafStrings, stString_copy(binaryTree->label)); - } -} - -struct List *binaryTree_getOrderedLeafStrings(struct BinaryTree *binaryTree) { - struct List *leafStrings = constructEmptyList(0, free); - binaryTree_getOrderedLeafStringsP(binaryTree, leafStrings); - return leafStrings; -} - -void binaryTree_depthFirstNumbers(struct BinaryTree *binaryTree) { - //get pre-order, post-order and mid-order depth first tree numbers - int64_t mid = 0; - int64_t leafNo = 0; - - binaryTree_depthFirstNumbers_Traverse(binaryTree, &mid, &leafNo); -} - -void printBinaryTreeP(FILE *file, struct BinaryTree *binaryTree) { - if (binaryTree->internal) { - fprintf(file, "("); - printBinaryTreeP(file, binaryTree->left); - if (binaryTree->right != NULL) { - fprintf(file, ","); - printBinaryTreeP(file, binaryTree->right); - } - fprintf(file, ")%s:%g", binaryTree->label, binaryTree->distance); - } else { - fprintf(file, "%s:%g", binaryTree->label, binaryTree->distance); - } -} - -void printBinaryTree(FILE *file, struct BinaryTree *binaryTree) { - printBinaryTreeP(file, binaryTree); - fprintf(file, ";\n"); -} - -void annotateTree_Fn(struct BinaryTree *bT, void *(*fn)(struct BinaryTree *i), - struct List *list) { - list->list[bT->traversalID->mid] = fn(bT); - if (bT->internal) { - annotateTree_Fn(bT->left, fn, list); - annotateTree_Fn(bT->right, fn, list); - } -} - -void annotateTree(struct BinaryTree *bT, void *(*fn)(struct BinaryTree *i), - struct List *list) { - int64_t i; - - list->length = 0; - for (i = 0; i < bT->traversalID->midEnd; i++) { - listAppend(list, NULL); - } - annotateTree_Fn(bT, fn, list); -} - -void getBinaryTreeNodesInMidOrder(struct BinaryTree *binaryTree, - struct BinaryTree **labels) { - labels[binaryTree->traversalID->mid] = binaryTree; - if (binaryTree->internal) { - getBinaryTreeNodesInMidOrder(binaryTree->left, labels); - getBinaryTreeNodesInMidOrder(binaryTree->right, labels); - } -} - -float linOriginRegression(struct List *pointsX, struct List *pointsY) { - int64_t i; - float j; - float k; - - j = 0.0; - k = 0.0; - assert(pointsX->length == pointsY->length); - for (i = 0; i < pointsX->length; i++) { - j += *((float *) pointsX->list[i]); - k += *((float *) pointsY->list[i]); - } - if (j != 0.0) { - return k / j; - } - return 1.0; -} - -int64_t floatValuesClose(double valueOne, double valueTwo, double precision) { - return (valueOne - valueTwo <= precision) || (valueTwo - valueOne - <= precision); -} - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//temp files -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -int64_t constructRandomDir(const char *tempFilePath, char **tempDir) { - /* - * Creates a random directory in the directory pointed to by tempFilePath. - * Initialses tempDir with this string. - * Returns 0 if okay. - */ - char *cA; - int64_t i; - - cA = st_malloc(sizeof(char) * (strlen(tempFilePath) + 50)); - sprintf(cA, "%s/", tempFilePath); - - for (i = strlen(tempFilePath) + 1; i < (int64_t) strlen(tempFilePath) + 11; i++) { - cA[i] = 65 + (RANDOM() * 26); - } - cA[i] = '\0'; - - i = mkdir(cA, S_IRWXU); - if (i != 0) { - free(cA); - st_logDebug( - "Something went wrong making temp dir in constructRandomDir\n"); - return i; - } - *tempDir = cA; - return 0; -} - -int64_t destructRandomDir(char *tempDir) { - /* - * Destructs the given temp dir and frees the appropriate string pointing - * to this directory. Partner of constructRandomDir. - */ - char *cA; - int64_t i; - - cA = st_malloc(sizeof(char) * (strlen(tempDir) + 50)); - sprintf(cA, "rm -rf %s", tempDir); - i = system(cA); - if (i != 0) { - return i; - } - free(cA); - free(tempDir); - return 0; -} - -struct TempFileTree *tempFileTree = NULL; - -void initialiseTempFileTree(char *rootDir, int64_t filesPerDir, - int64_t levelNumber) { - tempFileTree = constructTempFileTree(rootDir, filesPerDir, levelNumber); -} - -char *getTempFile(void) { - /* - * Gets a temporary file, using the tempFileTree, if initialised. - */ - if (tempFileTree != NULL) { - return tempFileTree_getTempFile(tempFileTree); - } - - char *tmpdir = NULL; - if ((getuid() == geteuid()) && (getgid() == getegid())) { - if (!((tmpdir = getenv("TMPDIR")))) { - tmpdir = getenv("TMP"); - } - } - if (!tmpdir) { - tmpdir = "/tmp"; - } - - static int64_t counter = 0; - while(counter < INT64_MAX) { - char *pattern = stString_print(tmpdir[strlen(tmpdir)-1] == '/' ? "%sstTmp%" PRIi64 "_%" PRIi64 "" : "%s/stTmp%" PRIi64 "_%" PRIi64 "", tmpdir, getpid(), counter++); - int fd = open(pattern, O_CREAT|O_EXCL, 0600); - if(fd >= 0) { - close(fd); - return pattern; - } - else if(errno != EEXIST){ - st_errnoAbort("Couldn't create temporary file's file descriptor for %s", pattern); - } - free(pattern); - } - st_errnoAbort("Exhausted temporary file patterns"); //This is pretty bloody unlikely - return NULL; -} - -void removeTempFile(char *tempFile) { - /* - * Removes a temporary file created by getTempFile. - * Also frees the associated string. - */ - if (tempFileTree != NULL) { - tempFileTree->tempFilesDestroyed++; - } - remove(tempFile); - free(tempFile); -} - -void removeAllTempFiles(void) { - assert(tempFileTree != NULL); - destructTempFileTree(tempFileTree); - tempFileTree = NULL; -} - -struct TempFileTree *constructTempFileTree(char *rootDir, int64_t filesPerDir, - int64_t levelNumber) { - struct TempFileTree *tempFileTree; - int64_t i, j; - char *cA; - char *cA2; - char *cA3; - - i = sizeof(char) * (strlen(rootDir) + 30 * levelNumber + 1); - cA = st_malloc(i); //generous safety space. - cA2 = st_malloc(i); - - tempFileTree = st_malloc(sizeof(struct TempFileTree)); - sprintf(cA, "%s/tempC", rootDir); - tempFileTree->rootDir = st_malloc(sizeof(char) * (strlen(cA) + 1)); - strcpy(tempFileTree->rootDir, cA); - mkdir(tempFileTree->rootDir, S_IRWXU); - - tempFileTree->filesPerDir = filesPerDir; - tempFileTree->levelNumber = levelNumber; - tempFileTree->levelsArray = st_malloc(sizeof(int64_t) * levelNumber); - for (i = 0; i < levelNumber; i++) { - tempFileTree->levelsArray[i] = 0; - } - sprintf(cA, "%s", tempFileTree->rootDir); //defensive - for (i = 0; i < levelNumber - 1; i++) { - sprintf(cA2, "%s/c0", cA); - cA3 = cA; - cA = cA2; - cA2 = cA3; - j = mkdir(cA, S_IRWXU); - if (j != 0) { - exit(1); - } - } - tempFileTree->tempFilesCreated = 0; - tempFileTree->tempFilesDestroyed = 0; - - free(cA); - free(cA2); - return tempFileTree; -} - -void destructTempFileTree(struct TempFileTree *tempFileTree) { - //does not currently dissmantle the directory structure/temp files! - char cA[1000]; - int64_t i; - - st_logDebug("Created: %" PRIi64 " temp files, actively destroyed: %" PRIi64 " temp files\n", - tempFileTree->tempFilesCreated, tempFileTree->tempFilesDestroyed); - - sprintf(cA, "rm -rf %s", tempFileTree->rootDir); - i = system(cA); - if (i != 0) { - exit(i); //failed to remove root directory structure of temp files. - } - free(tempFileTree->levelsArray); - free(tempFileTree->rootDir); - free(tempFileTree); -} - -char *tempFileTree_getTempFile(struct TempFileTree *tempFileTree) { - int64_t i, j, k; - char *cA; - char *cA2; - char *cA3; - char *cA4; - FILE *fileHandle; - - i = sizeof(char) * (strlen(tempFileTree->rootDir) + 30 - * tempFileTree->levelNumber + 1); - cA = st_malloc(i); //generous safety space. - cA2 = st_malloc(i); - cA4 = NULL; - for (i = tempFileTree->levelNumber - 1; i >= 0; i--) { - if (tempFileTree->levelsArray[i] == tempFileTree->filesPerDir) { - if (i == 0) { - fprintf(stderr, "Run out of temporary files!\n"); - exit(1); - } - tempFileTree->levelsArray[i] = 0; - } else { - tempFileTree->levelsArray[i] += 1; - if (i != tempFileTree->levelNumber - 1) { - for (j = i; j < tempFileTree->levelNumber - 1; j++) { - sprintf(cA, "%s", tempFileTree->rootDir); - for (k = 0; k <= j; k++) { - sprintf(cA2, "%s/c" INT_STRING, cA, - tempFileTree->levelsArray[k]); - cA3 = cA; - cA = cA2; - cA2 = cA3; - } - mkdir(cA, S_IRWXU); - } - } - sprintf(cA, "%s", tempFileTree->rootDir); - for (j = 0; j < tempFileTree->levelNumber; j++) { - sprintf(cA2, "%s/c" INT_STRING, cA, - tempFileTree->levelsArray[j]); - cA3 = cA; - cA = cA2; - cA2 = cA3; - } - cA4 = st_malloc(sizeof(char) * (strlen(cA) + 1)); - strcpy(cA4, cA); - break; - } - } - assert(cA4 != NULL); - fileHandle = fopen(cA4, "w"); - fclose(fileHandle); - free(cA); - free(cA2); - tempFileTree->tempFilesCreated++; - return cA4; -} - -/* - * Graphviz functions. - */ - -void graphViz_addNodeToGraph(const char *nodeName, FILE *graphFileHandle, - const char *label, double width, double height, const char *shape, - const char *colour, int64_t fontsize) { - /* - * Adds a node to the graph. - */ - fprintf(graphFileHandle, - "node[width=%f,height=%f,shape=%s,colour=%s,fontsize=%" PRIi64 "];\n", - width, height, shape, colour, fontsize); - fprintf(graphFileHandle, "n%sn [label=\"%s\"];\n", nodeName, label); -} - -void graphViz_addEdgeToGraph(const char *parentNodeName, - const char *childNodeName, FILE *graphFileHandle, const char *label, - const char *colour, double length, double weight, const char *direction) { - /* - * Links two nodes in the graph together. - */ - fprintf(graphFileHandle, "edge[color=%s,len=%f,weight=%f,dir=%s];\n", - colour, length, weight, direction); - fprintf(graphFileHandle, "n%sn -- n%sn [label=\"%s\"];\n", parentNodeName, - childNodeName, label); -} - -void graphViz_setupGraphFile(FILE *graphFileHandle) { - /* - * Sets up the dot file. - */ - fprintf(graphFileHandle, "graph G {\n"); - fprintf(graphFileHandle, "overlap=false\n"); -} - -void graphViz_finishGraphFile(FILE *graphFileHandle) { - /* - * Finishes up the dot file. - */ - fprintf(graphFileHandle, "}\n"); -} - -static int64_t getColour_Index = 0; -const char *graphViz_getColour(void) { - /* - * Returns a valid colour. - */ - getColour_Index++; - static char *colours[] = { "red", "blue", "green", "yellow", "cyan", - "magenta", "orange", "purple", "brown", "black", "grey" }; - return colours[getColour_Index % 11]; -} - -void arrayShuffle(void **array, int64_t n) { - /* Arrange the N elements of ARRAY in random order. - Only effective if N is much smaller than RAND_MAX; - if this may not be the case, use a better random - number generator. */ - if (n > 1) { - int64_t i; - for (i = 0; i < n - 1; i++) { - int64_t j = i + rand() / (RAND_MAX / (n - i) + 1); - void *t = array[j]; - array[j] = array[i]; - array[i] = t; - } - } -} - diff --git a/C/impl/fastCMaths.c b/C/impl/fastCMaths.c deleted file mode 100644 index 6d462a6..0000000 --- a/C/impl/fastCMaths.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/*This code is taken and adapted directly from the probcons library. - */ - -///////////////////////////////////////////////////////////////// -// FLOAT_32.h -// -// Routines for doing math operations in PROBCONS. -///////////////////////////////////////////////////////////////// -#include -#include -#include -#include - -#include "fastCMaths.h" -#include "sonLib.h" - -//typedef FLOAT_32 FLOAT_32; - -///////////////////////////////////////////////////////////////// -// LOG() -// -// Compute the logarithm of x. -///////////////////////////////////////////////////////////////// - -float LOG (float x){ - return log (x); -} - -///////////////////////////////////////////////////////////////// -// EXP() -// -// Computes exp(x). -///////////////////////////////////////////////////////////////// - -float EXP (float x){ - return exp(x); - if (x > -2){ - if (x > -0.5){ - if (x > 0) { - return exp(x); - } - return (((0.03254409303190190000*x + 0.16280432765779600000)*x + 0.49929760485974900000)*x + 0.99995149601363700000)*x + 0.99999925508501600000; - } - if (x > -1) { - return (((0.01973899026052090000*x + 0.13822379685007000000)*x + 0.48056651562365000000)*x + 0.99326940370383500000)*x + 0.99906756856399500000; - } - return (((0.00940528203591384000*x + 0.09414963667859410000)*x + 0.40825793595877300000)*x + 0.93933625499130400000)*x + 0.98369508190545300000; - } - if (x > -8){ - if (x > -4) { - return (((0.00217245711583303000*x + 0.03484829428350620000)*x + 0.22118199801337800000)*x + 0.67049462206469500000)*x + 0.83556950223398500000; - } - return (((0.00012398771025456900*x + 0.00349155785951272000)*x + 0.03727721426017900000)*x + 0.17974997741536900000)*x + 0.33249299994217400000; - } - if (x > -16) { - return (((0.00000051741713416603*x + 0.00002721456879608080)*x + 0.00053418601865636800)*x + 0.00464101989351936000)*x + 0.01507447981459420000; - } - return 0; -} - -/*const FLOAT_32 EXP_UNDERFLOW_THRESHOLD = -4.6; -const FLOAT_32 LOG_UNDERFLOW_THRESHOLD = 7.5;*/ - -///////////////////////////////////////////////////////////////// -// LOOKUP() -// -// Computes log (exp (x) + 1), for 0 <= x <= 7.5. -///////////////////////////////////////////////////////////////// - -float LOOKUP (float x){ - //return log (exp (x) + 1); - assert (x >= 0.00f); - assert (x <= LOG_UNDERFLOW_THRESHOLD); - if (x <= 1.00f) return ((-0.009350833524763f * x + 0.130659527668286f) * x + 0.498799810682272f) * x + 0.693203116424741f; - if (x <= 2.50f) return ((-0.014532321752540f * x + 0.139942324101744f) * x + 0.495635523139337f) * x + 0.692140569840976f; - if (x <= 4.50f) return ((-0.004605031767994f * x + 0.063427417320019f) * x + 0.695956496475118f) * x + 0.514272634594009f; - assert (x <= LOG_UNDERFLOW_THRESHOLD); - return ((-0.000458661602210f * x + 0.009695946122598f) * x + 0.930734667215156f) * x + 0.168037164329057f; -} - -///////////////////////////////////////////////////////////////// -// LOG_PLUS_EQUALS() -// -// Add two log probabilities and store in the first argument -///////////////////////////////////////////////////////////////// - -void LOG_PLUS_EQUALS (float *x, float y){ - if (*x < y) - *x = (*x == LOG_ZERO || y - *x >= LOG_UNDERFLOW_THRESHOLD) ? y : LOOKUP(y-*x) + *x; - else - *x = (y == LOG_ZERO || *x - y >= LOG_UNDERFLOW_THRESHOLD) ? *x : LOOKUP(*x-y) + y; -} - - -///////////////////////////////////////////////////////////////// -// LOG_ADD() -// -// Add two log probabilities -///////////////////////////////////////////////////////////////// - -float LOG_ADD (float x, float y){ - if (x < y) return (x == LOG_ZERO || y - x >= LOG_UNDERFLOW_THRESHOLD) ? y : LOOKUP(y-x) + x; - return (y == LOG_ZERO || x - y >= LOG_UNDERFLOW_THRESHOLD) ? x : LOOKUP(x-y) + y; -} - - -///////////////////////////////////////////////////////////////// -// LOG_ADD() -// -// Add three log probabilities -///////////////////////////////////////////////////////////////// - -float LOG_ADD_THREE (float x1, float x2, float x3){ - return LOG_ADD (x1, LOG_ADD (x2, x3)); -} - -///////////////////////////////////////////////////////////////// -// MAX_EQUALS() -// -// Chooses maximum of two arguments and stores it in the first argument -///////////////////////////////////////////////////////////////// - -void MAX_PLUS_EQUALS (float *x, float y){ - if ((*x) < y) - *x = y; -} - -///////////////////////////////////////////////////////////////// -// RANDOM() -// -// Return random FLOAT_32 in range [0 - 1.0 } -///////////////////////////////////////////////////////////////// -float RANDOM(void) { - static const float i = (RAND_MAX+1.0)*1.0f; - return rand()/i; -} - -///////////////////////////////////////////////////////////////// -// RANDOM() -// -// Return random FLOAT_32 in range [0 - 1.0 } -///////////////////////////////////////////////////////////////// -float RANDOM_LOG(void) { - return LOG(RANDOM()); -} diff --git a/C/impl/hashTableC.c b/C/impl/hashTableC.c deleted file mode 100644 index 0755547..0000000 --- a/C/impl/hashTableC.c +++ /dev/null @@ -1,307 +0,0 @@ - -/* Copyright (C) 2004 Christopher Clark */ - -#include "hashTableC.h" -#include "hashTablePrivateC.h" -#include -#include -#include -#include - -#include "sonLibGlobalsInternal.h" - -/* - Credit for primes table: Aaron Krowne - http://br.endernet.org/~akrowne/ - http://planetmath.org/encyclopedia/GoodHashTablePrimes.html - */ -static const uint64_t primes[] = { 53, 97, 193, 389, 769, 1543, 3079, 6151, - 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, - 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, - 805306457, 1610612741 }; -const uint64_t prime_table_length = sizeof(primes) / sizeof(primes[0]); -const float max_load_factor = 0.65; - -/* indexFor */ -static uint64_t indexFor(uint64_t tablelength, uint64_t hashvalue) { - return (hashvalue % tablelength); -} - -/*****************************************************************************/ -struct hashtable * -create_hashtable(uint64_t minsize, uint64_t(*hashf)(const void*), int(*eqf)( - const void*, const void*), void(*keyFree)(void *), void(*valueFree)( - void *)) { - struct hashtable *h; - uint64_t pindex, size = primes[0]; - /* Check requested hashtable isn't too large */ - if (minsize > (1u << 30)) - return NULL; - /* Enforce size as prime */ - for (pindex = 0; pindex < prime_table_length; pindex++) { - if (primes[pindex] > minsize) { - size = primes[pindex]; - break; - } - } - h = (struct hashtable *) st_malloc(sizeof(struct hashtable)); - if (NULL == h) - return NULL; /*oom*/ - h->table = (struct entry **) st_malloc(sizeof(struct entry*) * size); - if (NULL == h->table) { - free(h); - return NULL; - } /*oom*/ - memset(h->table, 0, size * sizeof(struct entry *)); - h->tablelength = size; - h->primeindex = pindex; - h->entrycount = 0; - h->hashfn = hashf; - h->eqfn = eqf; - h->loadlimit = (uint64_t) ceil(size * max_load_factor); - //my additions - h->keyFree = keyFree; - h->valueFree = valueFree; - return h; -} - -/*****************************************************************************/ -uint64_t hashP(struct hashtable *h, void *k) { - /* Aim to protect against poor hash functions by adding logic here - * - logic taken from java 1.4 hashtable source */ - uint64_t i = h->hashfn(k); - i += ~(i << 9); - i ^= ((i >> 14) | (i << 18)); /* >>> */ - i += (i << 4); - i ^= ((i >> 10) | (i << 22)); /* >>> */ - return i; -} - -/*****************************************************************************/ -static int64_t hashtable_expand(struct hashtable *h) { - /* Double the size of the table to accomodate more entries */ - struct entry **newtable; - struct entry *e; - //struct entry **pE; - uint64_t newsize, i, index; - /* Check we're not hitting max capacity */ - if (h->primeindex == (prime_table_length - 1)) - return 0; - newsize = primes[++(h->primeindex)]; - newtable = (struct entry **) st_malloc(sizeof(struct entry*) * newsize); - if (NULL != newtable) { - memset(newtable, 0, newsize * sizeof(struct entry *)); - /* This algorithm is not 'stable'. ie. it reverses the list - * when it transfers entries between the tables */ - for (i = 0; i < h->tablelength; i++) { - while (NULL != (e = h->table[i])) { - h->table[i] = e->next; - index = indexFor(newsize, e->h); - e->next = newtable[index]; - newtable[index] = e; - } - } - free(h->table); - h->table = newtable; - } - /* Plan B: realloc instead */ - else { - return 0; //the realloc doesn't always work - /*newtable = (struct entry **) - realloc(h->table, newsize * sizeof(struct entry *)); - if (NULL == newtable) { (h->primeindex)--; return 0; } - h->table = newtable; - memset(newtable[h->tablelength], 0, newsize - h->tablelength); - for (i = 0; i < h->tablelength; i++) { - for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) { - index = indexFor(newsize,e->h); - if (index == i) - { - pE = &(e->next); - } - else - { - *pE = e->next; - e->next = newtable[index]; - newtable[index] = e; - } - } - } */ - } - h->tablelength = newsize; - h->loadlimit = (uint64_t) ceil(newsize * max_load_factor); - return -1; -} - -/*****************************************************************************/ -uint64_t hashtable_count(struct hashtable *h) { - return h->entrycount; -} - -/*****************************************************************************/ -int64_t hashtable_insert(struct hashtable *h, void *k, void *v) { - /* This method allows duplicate keys - but they shouldn't be used */ - uint64_t index; - struct entry *e; - if (++(h->entrycount) > h->loadlimit) { - /* Ignore the return value. If expand fails, we should - * still try cramming just this value INT_32o the existing table - * -- we may not have memory for a larger table, but one more - * element may be ok. Next time we insert, we'll try expanding again.*/ - if (!hashtable_expand(h)) { - fprintf(stderr, "Expand hash failed \n"); - exit(1); - } - } - e = (struct entry *) st_malloc(sizeof(struct entry)); - if (NULL == e) { - --(h->entrycount); - return 0; - } /*oom*/ - e->h = hashP(h, k); - index = indexFor(h->tablelength, e->h); - e->k = k; - e->v = v; - e->next = h->table[index]; - h->table[index] = e; - return -1; -} - -/*****************************************************************************/ -void * /* returns value associated with key */ -hashtable_search(struct hashtable *h, void *k) { - struct entry *e; - uint64_t hashvalue, index; - hashvalue = hashP(h, k); - index = indexFor(h->tablelength, hashvalue); - e = h->table[index]; - while (NULL != e) { - /* Check hash value to short circuit heavier comparison */ - if ((hashvalue == e->h) && (h->eqfn(k, e->k))) - return e->v; - e = e->next; - } - return NULL; -} - -/*****************************************************************************/ -void * /* returns value associated with key */ -hashtable_remove(struct hashtable *h, void *k, int64_t freeKey) { - /* TODO: consider compacting the table when the load factor drops enough, - * or provide a 'compact' method. */ - - struct entry *e; - struct entry **pE; - void *v; - uint64_t hashvalue, index; - - hashvalue = hashP(h, k); - index = indexFor(h->tablelength, hashP(h, k)); - pE = &(h->table[index]); - e = *pE; - while (NULL != e) { - /* Check hash value to short circuit heavier comparison */ - if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { - *pE = e->next; - h->entrycount--; - v = e->v; - if (freeKey) { - h->keyFree(e->k); - } - free(e); - return v; - } - pE = &(e->next); - e = e->next; - } - return NULL; -} - -/*****************************************************************************/ -/* destroy */ -void hashtable_destroy(struct hashtable *h, int64_t free_values, - int64_t free_keys) { - uint64_t i; - struct entry *e, *f; - struct entry **table = h->table; - if (free_keys) { - if (free_values) { - for (i = 0; i < h->tablelength; i++) { - e = table[i]; - while (NULL != e) { - f = e; - e = e->next; - h->keyFree(f->k); - h->valueFree(f->v); - free(f); - } - } - } else { - for (i = 0; i < h->tablelength; i++) { - e = table[i]; - while (NULL != e) { - f = e; - e = e->next; - h->keyFree(f->k); - free(f); - } - } - } - } else { - if (free_values) { - for (i = 0; i < h->tablelength; i++) { - e = table[i]; - while (NULL != e) { - f = e; - e = e->next; - h->valueFree(f->v); - free(f); - } - } - } else { - for (i = 0; i < h->tablelength; i++) { - e = table[i]; - while (NULL != e) { - f = e; - e = e->next; - free(f); - } - } - } - } - free(h->table); - free(h); -} - -/* - * Copyright (c) 2002, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/C/impl/hashTableC_itr.c b/C/impl/hashTableC_itr.c deleted file mode 100644 index e3c5d2c..0000000 --- a/C/impl/hashTableC_itr.c +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright (C) 2002, 2004 Christopher Clark */ - -#include "hashTableC.h" -#include "hashTablePrivateC.h" -#include "hashTableC_itr.h" -#include /* defines NULL */ -#include "sonLibGlobalsInternal.h" - - -/* indexFor */ -static uint64_t -indexFor(uint64_t tablelength, uint64_t hashvalue) { - return (hashvalue % tablelength); -} - -/*****************************************************************************/ -/* hashtable_iterator - iterator constructor */ - -struct hashtable_itr * -hashtable_iterator(struct hashtable *h) -{ - unsigned int i, tablelength; - struct hashtable_itr *itr = (struct hashtable_itr *) - st_malloc(sizeof(struct hashtable_itr)); - if (NULL == itr) return NULL; - itr->h = h; - itr->e = NULL; - itr->parent = NULL; - tablelength = h->tablelength; - itr->index = tablelength; - if (0 == h->entrycount) return itr; - - for (i = 0; i < tablelength; i++) - { - if (NULL != h->table[i]) - { - itr->e = h->table[i]; - itr->index = i; - break; - } - } - return itr; -} - -/*****************************************************************************/ -/* advance - advance the iterator to the next element - * returns zero if advanced to end of table */ - -int -hashtable_iterator_advance(struct hashtable_itr *itr) -{ - unsigned int j,tablelength; - struct entry **table; - struct entry *next; - if (NULL == itr->e) return 0; /* stupidity check */ - - next = itr->e->next; - if (NULL != next) - { - itr->parent = itr->e; - itr->e = next; - return -1; - } - tablelength = itr->h->tablelength; - itr->parent = NULL; - if (tablelength <= (j = ++(itr->index))) - { - itr->e = NULL; - return 0; - } - table = itr->h->table; - while (NULL == (next = table[j])) - { - if (++j >= tablelength) - { - itr->index = tablelength; - itr->e = NULL; - return 0; - } - } - itr->index = j; - itr->e = next; - return -1; -} - -/*****************************************************************************/ -/* remove - remove the entry at the current iterator position - * and advance the iterator, if there is a successive - * element. - * If you want the value, read it before you remove: - * beware memory leaks if you don't. - * Returns zero if end of iteration. */ - -int -hashtable_iterator_remove(struct hashtable_itr *itr) -{ - struct entry *remember_e, *remember_parent; - int ret; - - /* Do the removal */ - if (NULL == (itr->parent)) - { - /* element is head of a chain */ - itr->h->table[itr->index] = itr->e->next; - } else { - /* element is mid-chain */ - itr->parent->next = itr->e->next; - } - /* itr->e is now outside the hashtable */ - remember_e = itr->e; - itr->h->entrycount--; - freekey(remember_e->k); - - /* Advance the iterator, correcting the parent */ - remember_parent = itr->parent; - ret = hashtable_iterator_advance(itr); - if (itr->parent == remember_e) { itr->parent = remember_parent; } - free(remember_e); - return ret; -} - -/*****************************************************************************/ -int /* returns zero if not found */ -hashtable_iterator_search(struct hashtable_itr *itr, - struct hashtable *h, void *k) -{ - struct entry *e, *parent; - unsigned int hashvalue, index; - - hashvalue = hashP(h,k); - index = indexFor(h->tablelength,hashvalue); - - e = h->table[index]; - parent = NULL; - while (NULL != e) - { - /* Check hash value to short circuit heavier comparison */ - if ((hashvalue == e->h) && (h->eqfn(k, e->k))) - { - itr->index = index; - itr->e = e; - itr->parent = parent; - itr->h = h; - return -1; - } - parent = e; - e = e->next; - } - return 0; -} - - -/* - * Copyright (c) 2002, 2004, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ diff --git a/C/impl/jsmn.c b/C/impl/jsmn.c deleted file mode 100644 index 9b76508..0000000 --- a/C/impl/jsmn.c +++ /dev/null @@ -1,334 +0,0 @@ -/*Copyright (c) 2010 Serge A. Zaitsev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE.*/ - -#include "jsmn.h" - -/** - * Allocates a fresh unused token from the token pull. - */ -static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, - jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *tok; - if (parser->toknext >= num_tokens) { - return NULL; - } - tok = &tokens[parser->toknext++]; - tok->start = tok->end = -1; - tok->size = 0; -#ifdef JSMN_PARENT_LINKS - tok->parent = -1; -#endif - return tok; -} - -/** - * Fills token type and boundaries. - */ -static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, - int start, int end) { - token->type = type; - token->start = start; - token->end = end; - token->size = 0; -} - -/** - * Fills next available token with JSON primitive. - */ -static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - int start; - - start = parser->pos; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - switch (js[parser->pos]) { -#ifndef JSMN_STRICT - /* In strict mode primitive must be followed by "," or "}" or "]" */ - case ':': -#endif - case '\t' : case '\r' : case '\n' : case ' ' : - case ',' : case ']' : case '}' : - goto found; - } - if (js[parser->pos] < 32 || js[parser->pos] >= 127) { - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } -#ifdef JSMN_STRICT - /* In strict mode primitive must be followed by a comma/object/array */ - parser->pos = start; - return JSMN_ERROR_PART; -#endif - -found: - if (tokens == NULL) { - parser->pos--; - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - parser->pos--; - return 0; -} - -/** - * Fills next token with JSON string. - */ -static int jsmn_parse_string(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - - int start = parser->pos; - - parser->pos++; - - /* Skip starting quote */ - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c = js[parser->pos]; - - /* Quote: end of string */ - if (c == '\"') { - if (tokens == NULL) { - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - return 0; - } - - /* Backslash: Quoted symbol expected */ - if (c == '\\' && parser->pos + 1 < len) { - int i; - parser->pos++; - switch (js[parser->pos]) { - /* Allowed escaped symbols */ - case '\"': case '/' : case '\\' : case 'b' : - case 'f' : case 'r' : case 'n' : case 't' : - break; - /* Allows escaped symbol \uXXXX */ - case 'u': - parser->pos++; - for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { - /* If it isn't a hex character we have an error */ - if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ - (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ - (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ - parser->pos = start; - return JSMN_ERROR_INVAL; - } - parser->pos++; - } - parser->pos--; - break; - /* Unexpected symbol */ - default: - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } - } - parser->pos = start; - return JSMN_ERROR_PART; -} - -/** - * Parse JSON string and fill tokens. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens) { - int r; - int i; - jsmntok_t *token; - int count = parser->toknext; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c; - jsmntype_t type; - - c = js[parser->pos]; - switch (c) { - case '{': case '[': - count++; - if (tokens == NULL) { - break; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) - return JSMN_ERROR_NOMEM; - if (parser->toksuper != -1) { - tokens[parser->toksuper].size++; -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - } - token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); - token->start = parser->pos; - parser->toksuper = parser->toknext - 1; - break; - case '}': case ']': - if (tokens == NULL) - break; - type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); -#ifdef JSMN_PARENT_LINKS - if (parser->toknext < 1) { - return JSMN_ERROR_INVAL; - } - token = &tokens[parser->toknext - 1]; - for (;;) { - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - token->end = parser->pos + 1; - parser->toksuper = token->parent; - break; - } - if (token->parent == -1) { - if(token->type != type || parser->toksuper == -1) { - return JSMN_ERROR_INVAL; - } - break; - } - token = &tokens[token->parent]; - } -#else - for (i = parser->toknext - 1; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - parser->toksuper = -1; - token->end = parser->pos + 1; - break; - } - } - /* Error if unmatched closing bracket */ - if (i == -1) return JSMN_ERROR_INVAL; - for (; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - parser->toksuper = i; - break; - } - } -#endif - break; - case '\"': - r = jsmn_parse_string(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - case '\t' : case '\r' : case '\n' : case ' ': - break; - case ':': - parser->toksuper = parser->toknext - 1; - break; - case ',': - if (tokens != NULL && parser->toksuper != -1 && - tokens[parser->toksuper].type != JSMN_ARRAY && - tokens[parser->toksuper].type != JSMN_OBJECT) { -#ifdef JSMN_PARENT_LINKS - parser->toksuper = tokens[parser->toksuper].parent; -#else - for (i = parser->toknext - 1; i >= 0; i--) { - if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { - if (tokens[i].start != -1 && tokens[i].end == -1) { - parser->toksuper = i; - break; - } - } - } -#endif - } - break; -#ifdef JSMN_STRICT - /* In strict mode primitives are: numbers and booleans */ - case '-': case '0': case '1' : case '2': case '3' : case '4': - case '5': case '6': case '7' : case '8': case '9': - case 't': case 'f': case 'n' : - /* And they must not be keys of the object */ - if (tokens != NULL && parser->toksuper != -1) { - jsmntok_t *t = &tokens[parser->toksuper]; - if (t->type == JSMN_OBJECT || - (t->type == JSMN_STRING && t->size != 0)) { - return JSMN_ERROR_INVAL; - } - } -#else - /* In non-strict mode every unquoted value is a primitive */ - default: -#endif - r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - -#ifdef JSMN_STRICT - /* Unexpected char in strict mode */ - default: - return JSMN_ERROR_INVAL; -#endif - } - } - - if (tokens != NULL) { - for (i = parser->toknext - 1; i >= 0; i--) { - /* Unmatched opened object or array */ - if (tokens[i].start != -1 && tokens[i].end == -1) { - return JSMN_ERROR_PART; - } - } - } - - return count; -} - -/** - * Creates a new parser based over a given buffer with an array of tokens - * available. - */ -void jsmn_init(jsmn_parser *parser) { - parser->pos = 0; - parser->toknext = 0; - parser->toksuper = -1; -} - diff --git a/C/impl/lz4.c b/C/impl/lz4.c deleted file mode 100644 index f15dcfc..0000000 --- a/C/impl/lz4.c +++ /dev/null @@ -1,907 +0,0 @@ -/* - LZ4 - Fast LZ compression algorithm - Copyright (C) 2011-2012, Yann Collet. - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html - - LZ4 source repository : http://code.google.com/p/lz4/ -*/ - -//************************************** -// Tuning parameters -//************************************** -// MEMORY_USAGE : -// Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) -// Increasing memory usage improves compression ratio -// Reduced memory usage can improve speed, due to cache effect -// Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache -#define MEMORY_USAGE 14 - -// BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE : -// This will provide a small boost to performance for big endian cpu, but the resulting compressed stream will be incompatible with little-endian CPU. -// You can set this option to 1 in situations where data will remain within closed environment -// This option is useless on Little_Endian CPU (such as x86) -//#define BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE 1 - - - -//************************************** -// CPU Feature Detection -//************************************** -// 32 or 64 bits ? -#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) ) // Detects 64 bits mode -# define LZ4_ARCH64 1 -#else -# define LZ4_ARCH64 0 -#endif - -// Little Endian or Big Endian ? -// Overwrite the #define below if you know your architecture endianess -#if defined (__GLIBC__) -# include -# if (__BYTE_ORDER == __BIG_ENDIAN) -# define LZ4_BIG_ENDIAN 1 -# endif -#elif (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)) -# define LZ4_BIG_ENDIAN 1 -#elif defined(__sparc) || defined(__sparc__) \ - || defined(__ppc__) || defined(_POWER) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) || defined(PPC) || defined(__powerpc__) || defined(__powerpc) || defined(powerpc) \ - || defined(__hpux) || defined(__hppa) \ - || defined(_MIPSEB) || defined(__s390__) -# define LZ4_BIG_ENDIAN 1 -#else -// Little Endian assumed. PDP Endian and other very rare endian format are unsupported. -#endif - -// Unaligned memory access is automatically enabled for "common" CPU, such as x86. -// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected -// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance -#if defined(__ARM_FEATURE_UNALIGNED) -# define LZ4_FORCE_UNALIGNED_ACCESS 1 -#endif - -// Define this parameter if your target system or compiler does not support hardware bit count -#if defined(_MSC_VER) && defined(_WIN32_WCE) // Visual Studio for Windows CE does not support Hardware bit count -# define LZ4_FORCE_SW_BITCOUNT -#endif - - -//************************************** -// Compiler Options -//************************************** -#if __STDC_VERSION__ >= 199901L // C99 -/* "restrict" is a known keyword */ -#else -# define restrict // Disable restrict -#endif - -#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) - -#ifdef _MSC_VER // Visual Studio -# include // For Visual 2005 -# if LZ4_ARCH64 // 64-bit -# pragma intrinsic(_BitScanForward64) // For Visual 2005 -# pragma intrinsic(_BitScanReverse64) // For Visual 2005 -# else -# pragma intrinsic(_BitScanForward) // For Visual 2005 -# pragma intrinsic(_BitScanReverse) // For Visual 2005 -# endif -#endif - -#ifdef _MSC_VER -# define lz4_bswap16(x) _byteswap_ushort(x) -#else -# define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))) -#endif - -#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) -# define expect(expr,value) (__builtin_expect ((expr),(value)) ) -#else -# define expect(expr,value) (expr) -#endif - -#define likely(expr) expect((expr) != 0, 1) -#define unlikely(expr) expect((expr) != 0, 0) - - -//************************************** -// Includes -//************************************** -#include // for malloc -#include // for memset -#include "lz4.h" - - -//************************************** -// Basic Types -//************************************** -#if defined(_MSC_VER) // Visual Studio does not support 'stdint' natively -# define BYTE unsigned __int8 -# define U16 unsigned __int16 -# define U32 unsigned __int32 -# define S32 __int32 -# define U64 unsigned __int64 -#else -# include -# define BYTE uint8_t -# define U16 uint16_t -# define U32 uint32_t -# define S32 int32_t -# define U64 uint64_t -#endif - -#ifndef LZ4_FORCE_UNALIGNED_ACCESS -# pragma pack(push, 1) -#endif - -typedef struct _U16_S { U16 v; } U16_S; -typedef struct _U32_S { U32 v; } U32_S; -typedef struct _U64_S { U64 v; } U64_S; - -#ifndef LZ4_FORCE_UNALIGNED_ACCESS -# pragma pack(pop) -#endif - -#define A64(x) (((U64_S *)(x))->v) -#define A32(x) (((U32_S *)(x))->v) -#define A16(x) (((U16_S *)(x))->v) - - -//************************************** -// Constants -//************************************** -#define MINMATCH 4 - -#define HASH_LOG (MEMORY_USAGE-2) -#define HASHTABLESIZE (1 << HASH_LOG) -#define HASH_MASK (HASHTABLESIZE - 1) - -// NOTCOMPRESSIBLE_DETECTIONLEVEL : -// Decreasing this value will make the algorithm skip faster data segments considered "incompressible" -// This may decrease compression ratio dramatically, but will be faster on incompressible data -// Increasing this value will make the algorithm search more before declaring a segment "incompressible" -// This could improve compression a bit, but will be slower on incompressible data -// The default value (6) is recommended -#define NOTCOMPRESSIBLE_DETECTIONLEVEL 6 -#define SKIPSTRENGTH (NOTCOMPRESSIBLE_DETECTIONLEVEL>2?NOTCOMPRESSIBLE_DETECTIONLEVEL:2) -#define STACKLIMIT 13 -#define HEAPMODE (HASH_LOG>STACKLIMIT) // Defines if memory is allocated into the stack (local variable), or into the heap (malloc()). -#define COPYLENGTH 8 -#define LASTLITERALS 5 -#define MFLIMIT (COPYLENGTH+MINMATCH) -#define MINLENGTH (MFLIMIT+1) - -#define MAXD_LOG 16 -#define MAX_DISTANCE ((1 << MAXD_LOG) - 1) - -#define ML_BITS 4 -#define ML_MASK ((1U<> ((MINMATCH*8)-HASH_LOG)) -#define LZ4_HASH_VALUE(p) LZ4_HASH_FUNCTION(A32(p)) -#define LZ4_WILDCOPY(s,d,e) do { LZ4_COPYPACKET(s,d) } while (d>3); - #elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_clzll(val) >> 3); - #else - int r; - if (!(val>>32)) { r=4; } else { r=0; val>>=32; } - if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } - r += (!val); - return r; - #endif -#else - #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r = 0; - _BitScanForward64( &r, val ); - return (int)(r>>3); - #elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_ctzll(val) >> 3); - #else - static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; - return DeBruijnBytePos[((U64)((val & -val) * 0x0218A392CDABBD3F)) >> 58]; - #endif -#endif -} - -#else - -static inline int LZ4_NbCommonBytes (register U32 val) -{ -#if defined(LZ4_BIG_ENDIAN) - #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r = 0; - _BitScanReverse( &r, val ); - return (int)(r>>3); - #elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_clz(val) >> 3); - #else - int r; - if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } - r += (!val); - return r; - #endif -#else - #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r; - _BitScanForward( &r, val ); - return (int)(r>>3); - #elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_ctz(val) >> 3); - #else - static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; - return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; - #endif -#endif -} - -#endif - - - -//****************************** -// Compression functions -//****************************** - -// LZ4_compressCtx : -// ----------------- -// Compress 'isize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'. -// If it cannot achieve it, compression will stop, and result of the function will be zero. -// return : the number of bytes written in buffer 'dest', or 0 if the compression fails - -static inline int LZ4_compressCtx(void** ctx, - const char* source, - char* dest, - int isize, - int maxOutputSize) -{ -#if HEAPMODE - struct refTables *srt = (struct refTables *) (*ctx); - HTYPE* HashTable; -#else - HTYPE HashTable[HASHTABLESIZE] = {0}; -#endif - - const BYTE* ip = (BYTE*) source; - INITBASE(base); - const BYTE* anchor = ip; - const BYTE* const iend = ip + isize; - const BYTE* const mflimit = iend - MFLIMIT; -#define matchlimit (iend - LASTLITERALS) - - BYTE* op = (BYTE*) dest; - BYTE* const oend = op + maxOutputSize; - - int length; - const int skipStrength = SKIPSTRENGTH; - U32 forwardH; - - - // Init - if (isizehashTable); - memset((void*)HashTable, 0, sizeof(srt->hashTable)); -#else - (void) ctx; -#endif - - - // First Byte - HashTable[LZ4_HASH_VALUE(ip)] = ip - base; - ip++; forwardH = LZ4_HASH_VALUE(ip); - - // Main Loop - for ( ; ; ) - { - int findMatchAttempts = (1U << skipStrength) + 3; - const BYTE* forwardIp = ip; - const BYTE* ref; - BYTE* token; - - // Find a match - do { - U32 h = forwardH; - int step = findMatchAttempts++ >> skipStrength; - ip = forwardIp; - forwardIp = ip + step; - - if unlikely(forwardIp > mflimit) { goto _last_literals; } - - forwardH = LZ4_HASH_VALUE(forwardIp); - ref = base + HashTable[h]; - HashTable[h] = ip - base; - - } while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip))); - - // Catch up - while ((ip>anchor) && (ref>(BYTE*)source) && unlikely(ip[-1]==ref[-1])) { ip--; ref--; } - - // Encode Literal length - length = (int)(ip - anchor); - token = op++; - if unlikely(op + length + (2 + 1 + LASTLITERALS) + (length>>8) > oend) return 0; // Check output limit -#ifdef _MSC_VER - if (length>=(int)RUN_MASK) - { - int len = length-RUN_MASK; - *token=(RUN_MASK<254) - { - do { *op++ = 255; len -= 255; } while (len>254); - *op++ = (BYTE)len; - memcpy(op, anchor, length); - op += length; - goto _next_match; - } - else - *op++ = (BYTE)len; - } - else *token = (length<=(int)RUN_MASK) - { - int len; - *token=(RUN_MASK< 254 ; len-=255) *op++ = 255; - *op++ = (BYTE)len; - } - else *token = (length<>8) > oend) return 0; // Check output limit - if (length>=(int)ML_MASK) - { - *token += ML_MASK; - length -= ML_MASK; - for (; length > 509 ; length-=510) { *op++ = 255; *op++ = 255; } - if (length > 254) { length-=255; *op++ = 255; } - *op++ = (BYTE)length; - } - else *token += length; - - // Test end of chunk - if (ip > mflimit) { anchor = ip; break; } - - // Fill table - HashTable[LZ4_HASH_VALUE(ip-2)] = ip - 2 - base; - - // Test next position - ref = base + HashTable[LZ4_HASH_VALUE(ip)]; - HashTable[LZ4_HASH_VALUE(ip)] = ip - base; - if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) { token = op++; *token=0; goto _next_match; } - - // Prepare next loop - anchor = ip++; - forwardH = LZ4_HASH_VALUE(ip); - } - -_last_literals: - // Encode Last Literals - { - int lastRun = (int)(iend - anchor); - if (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) return 0; - if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK< 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } - else *op++ = (lastRun<> ((MINMATCH*8)-HASHLOG64K)) -#define LZ4_HASH64K_VALUE(p) LZ4_HASH64K_FUNCTION(A32(p)) -static inline int LZ4_compress64kCtx(void** ctx, - const char* source, - char* dest, - int isize, - int maxOutputSize) -{ -#if HEAPMODE - struct refTables *srt = (struct refTables *) (*ctx); - U16* HashTable; -#else - U16 HashTable[HASH64KTABLESIZE] = {0}; -#endif - - const BYTE* ip = (BYTE*) source; - const BYTE* anchor = ip; - const BYTE* const base = ip; - const BYTE* const iend = ip + isize; - const BYTE* const mflimit = iend - MFLIMIT; -#define matchlimit (iend - LASTLITERALS) - - BYTE* op = (BYTE*) dest; - BYTE* const oend = op + maxOutputSize; - - int len, length; - const int skipStrength = SKIPSTRENGTH; - U32 forwardH; - - - // Init - if (isizehashTable); - memset((void*)HashTable, 0, sizeof(srt->hashTable)); -#else - (void) ctx; -#endif - - - // First Byte - ip++; forwardH = LZ4_HASH64K_VALUE(ip); - - // Main Loop - for ( ; ; ) - { - int findMatchAttempts = (1U << skipStrength) + 3; - const BYTE* forwardIp = ip; - const BYTE* ref; - BYTE* token; - - // Find a match - do { - U32 h = forwardH; - int step = findMatchAttempts++ >> skipStrength; - ip = forwardIp; - forwardIp = ip + step; - - if (forwardIp > mflimit) { goto _last_literals; } - - forwardH = LZ4_HASH64K_VALUE(forwardIp); - ref = base + HashTable[h]; - HashTable[h] = (U16)(ip - base); - - } while (A32(ref) != A32(ip)); - - // Catch up - while ((ip>anchor) && (ref>(BYTE*)source) && (ip[-1]==ref[-1])) { ip--; ref--; } - - // Encode Literal length - length = (int)(ip - anchor); - token = op++; - if unlikely(op + length + (2 + 1 + LASTLITERALS) + (length>>8) > oend) return 0; // Check output limit -#ifdef _MSC_VER - if (length>=(int)RUN_MASK) - { - int len = length-RUN_MASK; - *token=(RUN_MASK<254) - { - do { *op++ = 255; len -= 255; } while (len>254); - *op++ = (BYTE)len; - memcpy(op, anchor, length); - op += length; - goto _next_match; - } - else - *op++ = (BYTE)len; - } - else *token = (length<=(int)RUN_MASK) { *token=(RUN_MASK< 254 ; len-=255) *op++ = 255; *op++ = (BYTE)len; } - else *token = (length<>8) > oend) return 0; // Check output limit - if (len>=(int)ML_MASK) { *token+=ML_MASK; len-=ML_MASK; for(; len > 509 ; len-=510) { *op++ = 255; *op++ = 255; } if (len > 254) { len-=255; *op++ = 255; } *op++ = (BYTE)len; } - else *token += len; - - // Test end of chunk - if (ip > mflimit) { anchor = ip; break; } - - // Fill table - HashTable[LZ4_HASH64K_VALUE(ip-2)] = (U16)(ip - 2 - base); - - // Test next position - ref = base + HashTable[LZ4_HASH64K_VALUE(ip)]; - HashTable[LZ4_HASH64K_VALUE(ip)] = (U16)(ip - base); - if (A32(ref) == A32(ip)) { token = op++; *token=0; goto _next_match; } - - // Prepare next loop - anchor = ip++; - forwardH = LZ4_HASH64K_VALUE(ip); - } - -_last_literals: - // Encode Last Literals - { - int lastRun = (int)(iend - anchor); - if (op + lastRun + 1 + (lastRun-RUN_MASK+255)/255 > oend) return 0; - if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK< 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } - else *op++ = (lastRun<>ML_BITS)) == RUN_MASK) { size_t len; for (;(len=*ip++)==255;length+=255){} length += len; } - - // copy literals - cpy = op+length; - if (cpy>oend-COPYLENGTH) - { - if (cpy != oend) goto _output_error; // Error : not enough place for another match (min 4) + 5 literals - memcpy(op, ip, length); - ip += length; - break; // EOF - } - LZ4_WILDCOPY(ip, op, cpy); ip -= (op-cpy); op = cpy; - - // get offset - LZ4_READ_LITTLEENDIAN_16(ref,cpy,ip); ip+=2; - if unlikely(ref < (BYTE* const)dest) goto _output_error; // Error : offset outside destination buffer - - // get matchlength - if ((length=(token&ML_MASK)) == ML_MASK) { for (;*ip==255;length+=255) {ip++;} length += *ip++; } - - // copy repeated sequence - if unlikely((op-ref)oend-(COPYLENGTH)-(STEPSIZE-4)) - { - if (cpy > oend-LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals - LZ4_SECURECOPY(ref, op, (oend-COPYLENGTH)); - while(op>ML_BITS)) == RUN_MASK) - { - int s=255; - while (likely(ipoend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) - { - if (cpy > oend) goto _output_error; // Error : writes beyond output buffer - if (ip+length != iend) goto _output_error; // Error : LZ4 format requires to consume all input at this stage (no match within the last 11 bytes, and at least 8 remaining input bytes for another match+literals) - memcpy(op, ip, length); - op += length; - break; // Necessarily EOF, due to parsing restrictions - } - LZ4_WILDCOPY(ip, op, cpy); ip -= (op-cpy); op = cpy; - - // get offset - LZ4_READ_LITTLEENDIAN_16(ref,cpy,ip); ip+=2; - if unlikely(ref < (BYTE* const)dest) goto _output_error; // Error : offset outside of destination buffer - - // get matchlength - if ((length=(token&ML_MASK)) == ML_MASK) - { - while likely(ipoend-(COPYLENGTH+(STEPSIZE-4))) - { - if (cpy > oend-LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals - LZ4_SECURECOPY(ref, op, (oend-COPYLENGTH)); - while(op -# if (__BYTE_ORDER == __BIG_ENDIAN) -# define LZ4_BIG_ENDIAN 1 -# endif -#elif (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)) -# define LZ4_BIG_ENDIAN 1 -#elif defined(__sparc) || defined(__sparc__) \ - || defined(__ppc__) || defined(_POWER) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) || defined(PPC) || defined(__powerpc__) || defined(__powerpc) || defined(powerpc) \ - || defined(__hpux) || defined(__hppa) \ - || defined(_MIPSEB) || defined(__s390__) -# define LZ4_BIG_ENDIAN 1 -#else -// Little Endian assumed. PDP Endian and other very rare endian format are unsupported. -#endif - -// Unaligned memory access is automatically enabled for "common" CPU, such as x86. -// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected -// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance -#if defined(__ARM_FEATURE_UNALIGNED) -# define LZ4_FORCE_UNALIGNED_ACCESS 1 -#endif - -// Define this parameter if your target system or compiler does not support hardware bit count -#if defined(_MSC_VER) && defined(_WIN32_WCE) // Visual Studio for Windows CE does not support Hardware bit count -# define LZ4_FORCE_SW_BITCOUNT -#endif - - -//************************************** -// Compiler Options -//************************************** -#if __STDC_VERSION__ >= 199901L // C99 - /* "restrict" is a known keyword */ -#else -# define restrict // Disable restrict -#endif - -#ifdef _MSC_VER -# define inline __inline // Visual is not C99, but supports some kind of inline -# define forceinline __forceinline -# include // For Visual 2005 -# if LZ4_ARCH64 // 64-bit -# pragma intrinsic(_BitScanForward64) // For Visual 2005 -# pragma intrinsic(_BitScanReverse64) // For Visual 2005 -# else -# pragma intrinsic(_BitScanForward) // For Visual 2005 -# pragma intrinsic(_BitScanReverse) // For Visual 2005 -# endif -#else -# ifdef __GNUC__ -# define forceinline inline __attribute__((always_inline)) -# else -# define forceinline inline -# endif -#endif - -#ifdef _MSC_VER // Visual Studio -#define lz4_bswap16(x) _byteswap_ushort(x) -#else -#define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))) -#endif - - -//************************************** -// Includes -//************************************** -#include // calloc, free -#include // memset, memcpy -#include "lz4hc.h" - -#define ALLOCATOR(s) calloc(1,s) -#define FREEMEM free -#define MEM_INIT memset - - -//************************************** -// Basic Types -//************************************** -#if defined(_MSC_VER) // Visual Studio does not support 'stdint' natively -#define BYTE unsigned __int8 -#define U16 unsigned __int16 -#define U32 unsigned __int32 -#define S32 __int32 -#define U64 unsigned __int64 -#else -#include -#define BYTE uint8_t -#define U16 uint16_t -#define U32 uint32_t -#define S32 int32_t -#define U64 uint64_t -#endif - -#ifndef LZ4_FORCE_UNALIGNED_ACCESS -#pragma pack(push, 1) -#endif - -typedef struct _U16_S { U16 v; } U16_S; -typedef struct _U32_S { U32 v; } U32_S; -typedef struct _U64_S { U64 v; } U64_S; - -#ifndef LZ4_FORCE_UNALIGNED_ACCESS -#pragma pack(pop) -#endif - -#define A64(x) (((U64_S *)(x))->v) -#define A32(x) (((U32_S *)(x))->v) -#define A16(x) (((U16_S *)(x))->v) - - -//************************************** -// Constants -//************************************** -#define MINMATCH 4 - -#define DICTIONARY_LOGSIZE 16 -#define MAXD (1<> ((MINMATCH*8)-HASH_LOG)) -#define HASH_VALUE(p) HASH_FUNCTION(A32(p)) -#define HASH_POINTER(p) (HashTable[HASH_VALUE(p)] + base) -#define DELTANEXT(p) chainTable[(size_t)(p) & MAXD_MASK] -#define GETNEXT(p) ((p) - (size_t)DELTANEXT(p)) - - -//************************************** -// Private functions -//************************************** -#if LZ4_ARCH64 - -inline static int LZ4_NbCommonBytes (register U64 val) -{ -#if defined(LZ4_BIG_ENDIAN) - #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r = 0; - _BitScanReverse64( &r, val ); - return (int)(r>>3); - #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_clzll(val) >> 3); - #else - int r; - if (!(val>>32)) { r=4; } else { r=0; val>>=32; } - if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } - r += (!val); - return r; - #endif -#else - #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r = 0; - _BitScanForward64( &r, val ); - return (int)(r>>3); - #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_ctzll(val) >> 3); - #else - static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; - return DeBruijnBytePos[((U64)((val & -val) * 0x0218A392CDABBD3F)) >> 58]; - #endif -#endif -} - -#else - -inline static int LZ4_NbCommonBytes (register U32 val) -{ -#if defined(LZ4_BIG_ENDIAN) - #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r; - _BitScanReverse( &r, val ); - return (int)(r>>3); - #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_clz(val) >> 3); - #else - int r; - if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } - r += (!val); - return r; - #endif -#else - #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r; - _BitScanForward( &r, val ); - return (int)(r>>3); - #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_ctz(val) >> 3); - #else - static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; - return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; - #endif -#endif -} - -#endif - - -inline static int LZ4HC_Init (LZ4HC_Data_Structure* hc4, const BYTE* base) -{ - MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable)); - MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable)); - hc4->nextToUpdate = base + LZ4_ARCH64; - hc4->base = base; - return 1; -} - - -inline static void* LZ4HC_Create (const BYTE* base) -{ - void* hc4 = ALLOCATOR(sizeof(LZ4HC_Data_Structure)); - - LZ4HC_Init ((LZ4HC_Data_Structure*)hc4, base); - return hc4; -} - - -inline static int LZ4HC_Free (void** LZ4HC_Data) -{ - FREEMEM(*LZ4HC_Data); - *LZ4HC_Data = NULL; - return (1); -} - - -// Update chains up to ip (excluded) -forceinline static void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip) -{ - U16* chainTable = hc4->chainTable; - HTYPE* HashTable = hc4->hashTable; - INITBASE(base,hc4->base); - - while(hc4->nextToUpdate < ip) - { - const BYTE* p = hc4->nextToUpdate; - size_t delta = (p) - HASH_POINTER(p); - if (delta>MAX_DISTANCE) delta = MAX_DISTANCE; - DELTANEXT(p) = (U16)delta; - HashTable[HASH_VALUE(p)] = (p) - base; - hc4->nextToUpdate++; - } -} - - -forceinline static size_t LZ4HC_CommonLength (const BYTE* p1, const BYTE* p2, const BYTE* const matchlimit) -{ - const BYTE* p1t = p1; - - while (p1tchainTable; - HTYPE* const HashTable = hc4->hashTable; - const BYTE* ref; - INITBASE(base,hc4->base); - int nbAttempts=MAX_NB_ATTEMPTS; - size_t repl=0, ml=0; - U16 delta; - - // HC4 match finder - LZ4HC_Insert(hc4, ip); - ref = HASH_POINTER(ip); - -#define REPEAT_OPTIMIZATION -#ifdef REPEAT_OPTIMIZATION - // Detect repetitive sequences of length <= 4 - if (ref >= ip-4) // potential repetition - { - if (A32(ref) == A32(ip)) // confirmed - { - delta = (U16)(ip-ref); - repl = ml = LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit) + MINMATCH; - *matchpos = ref; - } - ref = GETNEXT(ref); - } -#endif - - while ((ref >= ip-MAX_DISTANCE) && (nbAttempts)) - { - nbAttempts--; - if (*(ref+ml) == *(ip+ml)) - if (A32(ref) == A32(ip)) - { - size_t mlt = LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit) + MINMATCH; - if (mlt > ml) { ml = mlt; *matchpos = ref; } - } - ref = GETNEXT(ref); - } - -#ifdef REPEAT_OPTIMIZATION - // Complete table - if (repl) - { - const BYTE* ptr = ip; - const BYTE* end; - - end = ip + repl - (MINMATCH-1); - while(ptr < end-delta) - { - DELTANEXT(ptr) = delta; // Pre-Load - ptr++; - } - do - { - DELTANEXT(ptr) = delta; - HashTable[HASH_VALUE(ptr)] = (ptr) - base; // Head of chain - ptr++; - } while(ptr < end); - hc4->nextToUpdate = end; - } -#endif - - return (int)ml; -} - - -forceinline static int LZ4HC_InsertAndGetWiderMatch (LZ4HC_Data_Structure* hc4, const BYTE* ip, const BYTE* startLimit, const BYTE* matchlimit, int longest, const BYTE** matchpos, const BYTE** startpos) -{ - U16* const chainTable = hc4->chainTable; - HTYPE* const HashTable = hc4->hashTable; - INITBASE(base,hc4->base); - const BYTE* ref; - int nbAttempts = MAX_NB_ATTEMPTS; - int delta = (int)(ip-startLimit); - - // First Match - LZ4HC_Insert(hc4, ip); - ref = HASH_POINTER(ip); - - while ((ref >= ip-MAX_DISTANCE) && (nbAttempts)) - { - nbAttempts--; - if (*(startLimit + longest) == *(ref - delta + longest)) - if (A32(ref) == A32(ip)) - { -#if 1 - const BYTE* reft = ref+MINMATCH; - const BYTE* ipt = ip+MINMATCH; - const BYTE* startt = ip; - - while (iptstartLimit) && (reft > hc4->base) && (startt[-1] == reft[-1])) {startt--; reft--;} - - if ((ipt-startt) > longest) - { - longest = (int)(ipt-startt); - *matchpos = reft; - *startpos = startt; - } - } - ref = GETNEXT(ref); - } - - return longest; -} - - -forceinline static int LZ4_encodeSequence(const BYTE** ip, BYTE** op, const BYTE** anchor, int ml, const BYTE* ref) -{ - int length, len; - BYTE* token; - - // Encode Literal length - length = (int)(*ip - *anchor); - token = (*op)++; - if (length>=(int)RUN_MASK) { *token=(RUN_MASK< 254 ; len-=255) *(*op)++ = 255; *(*op)++ = (BYTE)len; } - else *token = (length<=(int)ML_MASK) { *token+=ML_MASK; len-=ML_MASK; for(; len > 509 ; len-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (len > 254) { len-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)len; } - else *token += len; - - // Prepare next loop - *ip += ml; - *anchor = *ip; - - return 0; -} - - -//**************************** -// Compression CODE -//**************************** - -int LZ4_compressHCCtx(LZ4HC_Data_Structure* ctx, - const char* source, - char* dest, - int isize) -{ - const BYTE* ip = (const BYTE*) source; - const BYTE* anchor = ip; - const BYTE* const iend = ip + isize; - const BYTE* const mflimit = iend - MFLIMIT; - const BYTE* const matchlimit = (iend - LASTLITERALS); - - BYTE* op = (BYTE*) dest; - - int ml, ml2, ml3, ml0; - const BYTE* ref=NULL; - const BYTE* start2=NULL; - const BYTE* ref2=NULL; - const BYTE* start3=NULL; - const BYTE* ref3=NULL; - const BYTE* start0; - const BYTE* ref0; - - ip++; - - // Main Loop - while (ip < mflimit) - { - ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref)); - if (!ml) { ip++; continue; } - - // saved, in case we would skip too much - start0 = ip; - ref0 = ref; - ml0 = ml; - -_Search2: - if (ip+ml < mflimit) - ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2); - else ml2 = ml; - - if (ml2 == ml) // No better match - { - LZ4_encodeSequence(&ip, &op, &anchor, ml, ref); - continue; - } - - if (start0 < ip) - { - if (start2 < ip + ml0) // empirical - { - ip = start0; - ref = ref0; - ml = ml0; - } - } - - // Here, start0==ip - if ((start2 - ip) < 3) // First Match too small : removed - { - ml = ml2; - ip = start2; - ref =ref2; - goto _Search2; - } - -_Search3: - // Currently we have : - // ml2 > ml1, and - // ip1+3 <= ip2 (usually < ip1+ml1) - if ((start2 - ip) < OPTIMAL_ML) - { - int correction; - int new_ml = ml; - if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML; - if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH; - correction = new_ml - (int)(start2 - ip); - if (correction > 0) - { - start2 += correction; - ref2 += correction; - ml2 -= correction; - } - } - // Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) - - if (start2 + ml2 < mflimit) - ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3); - else ml3 = ml2; - - if (ml3 == ml2) // No better match : 2 sequences to encode - { - // ip & ref are known; Now for ml - if (start2 < ip+ml) ml = (int)(start2 - ip); - // Now, encode 2 sequences - LZ4_encodeSequence(&ip, &op, &anchor, ml, ref); - ip = start2; - LZ4_encodeSequence(&ip, &op, &anchor, ml2, ref2); - continue; - } - - if (start3 < ip+ml+3) // Not enough space for match 2 : remove it - { - if (start3 >= (ip+ml)) // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 - { - if (start2 < ip+ml) - { - int correction = (int)(ip+ml - start2); - start2 += correction; - ref2 += correction; - ml2 -= correction; - if (ml2 < MINMATCH) - { - start2 = start3; - ref2 = ref3; - ml2 = ml3; - } - } - - LZ4_encodeSequence(&ip, &op, &anchor, ml, ref); - ip = start3; - ref = ref3; - ml = ml3; - - start0 = start2; - ref0 = ref2; - ml0 = ml2; - goto _Search2; - } - - start2 = start3; - ref2 = ref3; - ml2 = ml3; - goto _Search3; - } - - // OK, now we have 3 ascending matches; let's write at least the first one - // ip & ref are known; Now for ml - if (start2 < ip+ml) - { - if ((start2 - ip) < (int)ML_MASK) - { - int correction; - if (ml > OPTIMAL_ML) ml = OPTIMAL_ML; - if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH; - correction = ml - (int)(start2 - ip); - if (correction > 0) - { - start2 += correction; - ref2 += correction; - ml2 -= correction; - } - } - else - { - ml = (int)(start2 - ip); - } - } - LZ4_encodeSequence(&ip, &op, &anchor, ml, ref); - - ip = start2; - ref = ref2; - ml = ml2; - - start2 = start3; - ref2 = ref3; - ml2 = ml3; - - goto _Search3; - - } - - // Encode Last Literals - { - int lastRun = (int)(iend - anchor); - if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK< 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } - else *op++ = (lastRun< -#include -#include - -#include "pairwiseAlignment.h" -#include "commonC.h" -#include "bioioC.h" - -struct AlignmentOperation *constructAlignmentOperation(int64_t type, int64_t length, float score) { - struct AlignmentOperation *oP; - - oP = st_malloc(sizeof(struct AlignmentOperation)); - - oP->opType = type; - oP->length = length; - oP->score = score; - - return oP; -} - -void destructAlignmentOperation(struct AlignmentOperation *alignmentOperation) { - free(alignmentOperation); -} - -void checkPairwiseAlignment(struct PairwiseAlignment *pA) { - int64_t i, j, k; - struct AlignmentOperation *op; - - assert(pA->start1 >= 0); - assert(pA->end1 >= 0); - assert(pA->strand1 == 0 || pA->strand1 == 1); - if(pA->strand1) { - assert(pA->start1 <= pA->end1); - } - else { - assert(pA->end1 <= pA->start1); - } - - assert(pA->start2 >= 0); - assert(pA->end2 >= 0); - assert(pA->strand2 == 0 || pA->strand2 == 1); - if(pA->strand2) { - assert(pA->start2 <= pA->end2); - } - else { - assert(pA->end2 <= pA->start2); - } - - //does not copy. - j = pA->start1; - k = pA->start2; - for(i=0; ioperationList->length; i++) { - op = pA->operationList->list[i]; - assert(op->length >= 0); - if(op->opType != PAIRWISE_INDEL_Y) { - j += pA->strand1 ? op->length : -op->length; - } - if(op->opType != PAIRWISE_INDEL_X) { - k += pA->strand2 ? op->length : -op->length; - } - } - - assert(j == pA->end1); - assert(k == pA->end2); -} - -struct PairwiseAlignment *constructPairwiseAlignment(char *contig1, int64_t start1, int64_t end1, int64_t strand1, - char *contig2, int64_t start2, int64_t end2, int64_t strand2, - float score, struct List *operationList) { - struct PairwiseAlignment *pA; - pA = st_malloc(sizeof(struct PairwiseAlignment)); - - pA->operationList = operationList; - - pA->contig1 = strcpy((char *)st_malloc(sizeof(char)*(1+strlen(contig1))), contig1); - pA->start1 = start1; - pA->end1 = end1; - pA->strand1 = strand1; - - pA->contig2 = strcpy((char *)st_malloc(sizeof(char)*(1+strlen(contig2))), contig2); - pA->start2 = start2; - pA->end2 = end2; - pA->strand2 = strand2; - - pA->score = score; - - checkPairwiseAlignment(pA); - return pA; -} - -void destructPairwiseAlignment(struct PairwiseAlignment *pA) { - destructList(pA->operationList); - free(pA->contig1); - free(pA->contig2); - free(pA); -} - -void logPairwiseAlignment(struct PairwiseAlignment *pA) { - st_logDebug("Pairwise alignment:"); - if(st_getLogLevel() == debug) { - cigarWrite(stderr, pA, TRUE); - } -} - -char cigarReadFn(char type, int64_t *withProb) { - *withProb = FALSE; - switch(type) { - case 'X': - *withProb = TRUE; - return PAIRWISE_MATCH; - case 'M': - return PAIRWISE_MATCH; - case 'Y': - *withProb = TRUE; - return PAIRWISE_INDEL_X; - case 'D': - return PAIRWISE_INDEL_X; - case 'Z': - *withProb = TRUE; - return PAIRWISE_INDEL_Y; - case 'I': - return PAIRWISE_INDEL_Y; - default: - assert(FALSE); - return '\0'; - } -} - -struct PairwiseAlignment *cigarRead(FILE *fileHandle) { - struct PairwiseAlignment *pA; - static char cA[BIG_STRING_ARRAY_SIZE+1]; //STRING_ARRAY_SIZE]; - int64_t type, length, withProb; - float score; - static char cA2[STRING_ARRAY_SIZE]; - static char cA3[STRING_ARRAY_SIZE]; - char *cA4; - char strand1, strand2; - - pA = st_malloc(sizeof(struct PairwiseAlignment)); - pA->operationList = constructEmptyList(0, (void (*)(void *))destructAlignmentOperation); - if(fscanf(fileHandle, "cigar: %s %" PRIi64 " %" PRIi64 " %c %s %" PRIi64 " %" PRIi64 " %c %f",\ - cA2, &pA->start2, &pA->end2, &strand2,\ - cA3, &pA->start1, &pA->end1, &strand1,\ - &pA->score) == 9) { - assert(strlen(cA2) <= STRING_ARRAY_SIZE); - assert(strlen(cA3) <= STRING_ARRAY_SIZE); - pA->contig2 = strcpy((char *)st_malloc(sizeof(char)*(1+strlen(cA2))), cA2); - pA->contig1 = strcpy((char *)st_malloc(sizeof(char)*(1+strlen(cA3))), cA3); - - assert(strand1 == '+' || strand1 == '-'); - assert(strand2 == '+' || strand2 == '-'); - pA->strand1 = strand1 == '+' ? 1 : 0; - pA->strand2 = strand2 == '+' ? 1 : 0; - - if(fgets(cA, BIG_STRING_ARRAY_SIZE, fileHandle) != NULL) { - assert(strlen(cA) < BIG_STRING_ARRAY_SIZE); - cA4 = cA; - while(parseString(&cA4, cA2) == 1) { - assert(strlen(cA2) == 1); - type = cigarReadFn(cA2[0], &withProb); - int64_t j = parseInt(&cA4, &length); - (void)j; - assert(j == 1); - if(withProb == TRUE) { - j = parseFloat(&cA4, &score); - (void)j; - assert(j == 1); - } - else { - score = 0.0; - } - listAppend(pA->operationList, constructAlignmentOperation(type, length, score)); - } - } - checkPairwiseAlignment(pA); - return pA; - } - else { - destructList(pA->operationList); - free(pA); - return NULL; - } -} - -char cigarWriteFn(int64_t type) { - switch(type) { - case PAIRWISE_MATCH: - return 'M'; - case PAIRWISE_INDEL_X: - return 'D'; - case PAIRWISE_INDEL_Y: - return 'I'; - default: - assert(FALSE); - return '\0'; - } -} - -char cigarWriteFnWProbs(int64_t type) { - switch(type) { - case PAIRWISE_MATCH: - return 'X'; - case PAIRWISE_INDEL_X: - return 'Y'; - case PAIRWISE_INDEL_Y: - return 'Z'; - default: - assert(FALSE); - return '\0'; - } -} - -void cigarWrite(FILE *fileHandle, struct PairwiseAlignment *pA, int64_t withProbs) { - int i; - struct AlignmentOperation *oP; - - fprintf(fileHandle, "cigar: %s %" PRIi64 " %" PRIi64 " %c %s %" PRIi64 " %" PRIi64 " %c %f",\ - pA->contig2, pA->start2, pA->end2, pA->strand2 ? '+' : '-',\ - pA->contig1, pA->start1, pA->end1, pA->strand1 ? '+' : '-',\ - pA->score); - if(withProbs == TRUE) { - for(i=0; ioperationList->length; i++) { - oP = pA->operationList->list[i]; - fprintf(fileHandle, " %c %" PRIi64 " %f", cigarWriteFnWProbs(oP->opType), oP->length, oP->score); - } - } - else { - for(i=0; ioperationList->length; i++) { - oP = pA->operationList->list[i]; - fprintf(fileHandle, " %c %" PRIi64 "", cigarWriteFn(oP->opType), oP->length); - } - } - fprintf(fileHandle, "\n"); -} - diff --git a/C/impl/sonLibAlign.c b/C/impl/sonLibAlign.c deleted file mode 100644 index 5c3dcd4..0000000 --- a/C/impl/sonLibAlign.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibAlign.c - * - * Created on: 01-Jun-2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsInternal.h" - diff --git a/C/impl/sonLibCache.c b/C/impl/sonLibCache.c deleted file mode 100644 index 454453a..0000000 --- a/C/impl/sonLibCache.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -//Cache functions - -#include "sonLibGlobalsInternal.h" - -struct stCache { - stSortedSet *cache; -}; - -typedef struct _cacheRecord { - /* - * A little object for storing records in the cache. - */ - int64_t key, start, size; - char *record; -} stCacheRecord; - -static int cacheRecord_cmp(const void *a, const void *b) { - const stCacheRecord *i = a; - const stCacheRecord *j = b; - if (i->key > j->key) { - return 1; - } - if (i->key < j->key) { - return -1; - } - if (i->start > j->start) { - return 1; - } - if (i->start < j->start) { - return -1; - } - return 0; -} - -static void cacheRecord_destruct(stCacheRecord *i) { - free(i->record); - free(i); -} - -static stCacheRecord getTempRecord(int64_t key, int64_t start, int64_t size) { - stCacheRecord record; - record.key = key; - record.start = start; - record.size = size; - record.record = NULL; - return record; -} - -static stCacheRecord *cacheRecord_construct(int64_t key, - const void *value, int64_t start, int64_t size, bool copyMemory) { - assert(value != NULL); - assert(size >= 0); - assert(start >= 0); - stCacheRecord *record = st_malloc(sizeof(stCacheRecord)); - record->key = key; - record->start = start; - record->size = size; - record->record = copyMemory ? memcpy(st_malloc(size), value, size) - : (char *) value; - return record; -} - -static stCacheRecord *getLessThanOrEqualRecord(stCache *cache, - int64_t key, int64_t start, int64_t size) { - stCacheRecord record = getTempRecord(key, start, size); - return stSortedSet_searchLessThanOrEqual(cache->cache, &record); -} - -static stCacheRecord *getGreaterThanOrEqualRecord(stCache *cache, - int64_t key, int64_t start, int64_t size) { - stCacheRecord record = getTempRecord(key, start, size); - return stSortedSet_searchGreaterThanOrEqual(cache->cache, &record); -} - -static bool recordContainedIn(stCacheRecord *record, int64_t key, - int64_t start, int64_t size) { - /* - * Returns non zero if the record is contained in the given range. - */ - return record->key == key && record->start >= start && record->start - + record->size <= start + size; -} - -static bool recordOverlapsWith(stCacheRecord *record, int64_t key, - int64_t start, int64_t size) { - /* - * Returns non zero if the record overlaps with the given range. - */ - if (record->key != key) { - return 0; - } - if (record->start >= start) { - return record->start < start + size; - } - return record->start + record->size > start; -} - -static bool recordsAdjacent(stCacheRecord *record1, stCacheRecord *record2) { - /* - * Returns non-zero if the records abut with record1 immediately before record2. - */ - assert(cacheRecord_cmp(record1, record2) <= 0); - assert(!recordOverlapsWith(record1, record2->key, record2->start, record2->size)); - assert(!recordContainedIn(record1, record2->key, record2->start, record2->size)); - return record1->key == record2->key && record1->start + record1->size - == record2->start; -} - -static stCacheRecord *mergeRecords(stCacheRecord *record1, - stCacheRecord *record2) { - /* - * Merges two adjacenct records. - */ - assert(recordsAdjacent(record1, record2)); - int64_t i = record1->size + record2->size; - char *j = memcpy(st_malloc(i), record1->record, record1->size); - memcpy(j + record1->size, record2->record, record2->size); - stCacheRecord *record3 = cacheRecord_construct(record1->key, j, - record1->start, i, 0); - return record3; -} - -void deleteRecord(stCache *cache, int64_t key, - int64_t start, int64_t size) { - assert(!stCache_containsRecord(cache, key, start, size)); //Will not delete a record wholly contained in. - stCacheRecord *record = getLessThanOrEqualRecord(cache, key, start, - size); - while (record != NULL && recordOverlapsWith(record, key, start, size)) { //could have multiple fragments in there to remove. - if (recordContainedIn(record, key, start, size)) { //We get rid of the record because it is contained in the range - stSortedSet_remove(cache->cache, record); - cacheRecord_destruct(record); - record = getLessThanOrEqualRecord(cache, key, start, size); - } else { //The range overlaps with, but is not fully contained in, so we trim it.. - assert(record->start < start); - assert(record->start + record->size > start); - record->size = start - record->start; - assert(record->size >= 0); - break; - } - } - record = getGreaterThanOrEqualRecord(cache, key, start, size); - while (record != NULL && recordOverlapsWith(record, key, start, size)) { //could have multiple fragments in there to remove. - if (recordContainedIn(record, key, start, size)) { //We get rid of the record because it is contained in the range - stSortedSet_remove(cache->cache, record); - cacheRecord_destruct(record); - record = getGreaterThanOrEqualRecord(cache, key, start, size); - } else { //The range overlaps with, but is not fully contained in, so we trim it.. - assert(record->start < start + size); - assert(record->start > start); - int64_t newSize = record->size - (start + size - record->start); - int64_t newStart = start + size; - assert(newSize >= 0); - char *newMem = memcpy(st_malloc(newSize), - record->record + start + size - record->start, newSize); - free(record->record); - record->record = newMem; - record->start = newStart; - record->size = newSize; - break; //We can break at this point as we have reached the end of the range (as the record overlapped) - } - } -} - - -/* - * Public functions - */ - -stCache *stCache_construct(void) { - stCache *cache = st_malloc(sizeof(stCache)); - cache->cache = stSortedSet_construct3(cacheRecord_cmp, - (void(*)(void *)) cacheRecord_destruct); - return cache; -} - -void stCache_destruct(stCache *cache) { - stSortedSet_destruct(cache->cache); - free(cache); -} - -void stCache_clear(stCache *cache) { - stSortedSet_destruct(cache->cache); - cache->cache = stSortedSet_construct3(cacheRecord_cmp, - (void(*)(void *)) cacheRecord_destruct); -} - -void stCache_setRecord(stCache *cache, int64_t key, - int64_t start, int64_t size, const void *value) { - //If the record is already contained we update a portion of it. - assert(value != NULL); - if (stCache_containsRecord(cache, key, start, size)) { - stCacheRecord *record = getLessThanOrEqualRecord(cache, key, - start, size); - assert(record != NULL); - assert(record->key == key); - assert(record->start <= start); - assert(record->start + record->size >= start + size); - memcpy(record->record + start - record->start, value, size); - return; - } - //Get rid of bits that are contained in this record.. - deleteRecord(cache, key, start, size); - //Now get any left and right bits - stCacheRecord *record1 = getLessThanOrEqualRecord(cache, key, start, - size); - stCacheRecord *record2 = cacheRecord_construct(key, value, start, - size, 1); - assert(record2 != NULL); - if (record1 != NULL && recordsAdjacent(record1, record2)) { - stCacheRecord *i = mergeRecords(record1, record2); - stSortedSet_remove(cache->cache, record1); - cacheRecord_destruct(record1); - cacheRecord_destruct(record2); - record2 = i; - } - stCacheRecord *record3 = getGreaterThanOrEqualRecord(cache, key, - start, size); - if (record3 != NULL && recordsAdjacent(record2, record3)) { - stCacheRecord *i = mergeRecords(record2, record3); - stSortedSet_remove(cache->cache, record3); - cacheRecord_destruct(record2); - cacheRecord_destruct(record3); - record2 = i; - } - stSortedSet_insert(cache->cache, record2); -} - -bool stCache_containsRecord(stCache *cache, int64_t key, - int64_t start, int64_t size) { - assert(start >= 0); - assert(size >= 0); - stCacheRecord *record = getLessThanOrEqualRecord(cache, key, start, - size); - if (record == NULL) { - return 0; - } - if (record->key != key) { - return 0; - } - assert(record->start <= start); - if (size != INT64_MAX && start + size > record->start + record->size) { //If the record has a known length check we have all that we want. - return 0; - } - return 1; -} - -void *stCache_getRecord(stCache *cache, int64_t key, - int64_t start, int64_t size, int64_t *sizeRead) { - if (stCache_containsRecord(cache, key, start, size)) { - stCacheRecord *record = getLessThanOrEqualRecord(cache, key, - start, size); - assert(record != NULL); - int64_t j = start - record->start; - int64_t i = size == INT64_MAX ? (record->size - j) : size; - assert(record->start <= start); - assert(j >= 0); - assert(j <= record->size); - assert(i >= 0); - assert(j + i <= record->size); - *sizeRead = i; - char *cA = st_malloc(i); - memcpy(cA, record->record + j, i); - return cA; - } - return NULL; -} - -bool stCache_recordsIdentical(const char *value, int64_t sizeOfRecord, - const char *updatedValue, int64_t updatedSizeOfRecord) { - if (sizeOfRecord != updatedSizeOfRecord) { - return 0; - } - for (int64_t j = 0; j < sizeOfRecord; j++) { - if (value[j] != updatedValue[j]) { - return 0; - } - } - return 1; -} diff --git a/C/impl/sonLibCommon.c b/C/impl/sonLibCommon.c deleted file mode 100644 index 5adc714..0000000 --- a/C/impl/sonLibCommon.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibLogging.c - * - * Created on: 24 May 2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsInternal.h" -#include - -static enum stLogLevel LOG_LEVEL = critical; - -void *st_malloc(size_t i) { - void *j; - j = malloc(i); - if (j == 0) { - fprintf(stderr, "Malloc failed with a request for: %zu bytes\n", i); - assert(0); - exit(1); - } - return j; -} - -void *st_realloc(void *buffer, size_t desiredSize) { - void *newBuffer = realloc(buffer, desiredSize); - if(newBuffer == NULL) { - fprintf(stderr, "Realloc failed with a request for: %zu bytes\n", desiredSize); - assert(0); - exit(1); - } - return newBuffer; -} - -void *st_calloc(int64_t elementNumber, size_t elementSize) { - void *k; - k = calloc(elementNumber, elementSize); - if (k == 0) { - fprintf(stderr, - "Calloc failed with request for %lld lots of %zu bytes\n", - (long long int) elementNumber, elementSize); - exit(1); - } - return k; -} - -void st_setLogLevelFromString(const char *string) { - if (string != NULL) { - char *string2 = stString_copy(string); - for (int64_t i = 0; i < strlen(string); i++) { - string2[i] = tolower(string2[i]); - } - if (strcmp(string2, "off") == 0) { - LOG_LEVEL = off; - } else if (strcmp(string2, "critical") == 0) { - LOG_LEVEL = critical; - } else if (strcmp(string2, "info") == 0) { - LOG_LEVEL = info; - st_logInfo("Set log level to INFO\n"); - } else { - if (strcmp(string2, "debug") != 0) { - st_errAbort("Unrecognised logging string %s", string); - } - LOG_LEVEL = debug; - st_logInfo("Set log level to DEBUG\n"); - } - free(string2); - } -} - -void st_setLogLevel(enum stLogLevel level) { - LOG_LEVEL = level; -} - -enum stLogLevel st_getLogLevel(void) { - return LOG_LEVEL; -} - -void st_logCritical(const char *string, ...) { - if (st_getLogLevel() >= critical) { - va_list ap; - va_start(ap, string); - vfprintf(stderr, string, ap); - va_end(ap); - } -} - -void st_logInfo(const char *string, ...) { - if (st_getLogLevel() >= info) { - va_list ap; - va_start(ap, string); - vfprintf(stderr, string, ap); - va_end(ap); - } -} - -void st_logDebug(const char *string, ...) { - if (st_getLogLevel() >= debug) { - va_list ap; - va_start(ap, string); - vfprintf(stderr, string, ap); - va_end(ap); - } -} - -void st_uglyf(const char *string, ...) { - va_list ap; - va_start(ap, string); - vfprintf(stderr, string, ap); - va_end(ap); -} - -int64_t st_system(const char *string, ...) { - static char cA[100000]; - int64_t i; - va_list ap; - va_start(ap, string); - vsprintf(cA, string, ap); - va_end(ap); - assert(strlen(cA) < 100000); - st_logDebug("Running command %s\n", cA); - i = system(cA); - //vfprintf(stdout, string, ap); - return i; -} - -void st_errAbort(char *format, ...) { - va_list ap; - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); - fputc('\n', stderr); - exit(1); -} - -void st_errnoAbort(char *format, ...) { - va_list ap; - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); - fprintf(stderr, ": %s\n", strerror(errno)); - exit(1); -} - -static int64_t reverse8Bytes(int64_t in) { - int64_t out; - char *inByte = (char *) ∈ - char *outByte = (char *) &out; - // looped for conciseness, hopefully it will be unrolled in - // practice. - for (int64_t i = 0; i < sizeof(int64_t); i++) { - outByte[i] = inByte[sizeof(int64_t) - i]; - } - return out; -} - -int64_t st_nativeInt64FromLittleEndian(int64_t in) { - static const int64_t one = 1; - if (*(char *)&one == 0) { - // big-endian - return reverse8Bytes(in); - } else { - // little-endian - return in; - } -} - -int64_t st_nativeInt64ToLittleEndian(int64_t in) { - static const int64_t one = 1; - if (*(char *)&one == 0) { - // big-endian - return reverse8Bytes(in); - } else { - // little-endian - return in; - } -} - -int64_t st_nativeInt64ToBigEndian(int64_t in) { - static const int64_t one = 1; - if (*(char *)&one == 0) { - // big-endian - return in; - } else { - // little-endian - return reverse8Bytes(in); - } -} - -int64_t st_nativeInt64FromBigEndian(int64_t in) { - static const int64_t one = 1; - if (*(char *)&one == 0) { - // big-endian - return in; - } else { - // little-endian - return reverse8Bytes(in); - } -} diff --git a/C/impl/sonLibCompression.c b/C/impl/sonLibCompression.c deleted file mode 100644 index adcf3a2..0000000 --- a/C/impl/sonLibCompression.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibCompression.c - * - * Created on: 03-Sep-2010 - * Author: benedictpaten - */ - -#include -#include "lz4hc.h" -#include "lz4.h" - -#include "sonLibGlobalsInternal.h" - -const char *ST_COMPRESSION_EXCEPTION_ID = "ST_COMPRESSION_EXCEPTION"; - -//2^30, should be safe and big enough to find good compression. -#define ST_LZ4_CHUNK_SIZE 1073741824 - -void *stCompression_compress(void *data, int64_t sizeInBytes, int64_t *compressedSizeInBytes, int64_t level) { - /* - * Uses the lz4 algorithm to provide very fast compression. - */ - int64_t bufferSize = sizeInBytes + (1 + sizeInBytes/255 + 16) * (1 + sizeInBytes/ST_LZ4_CHUNK_SIZE); - char *buffer = st_malloc(sizeof(char) * bufferSize); - int64_t outputOffset=0; - /* - * Breaks sequence to compress up into 1 gig chunks, to avoid overflows. - */ - for(int64_t inputOffset=0; inputOffset < sizeInBytes; inputOffset += ST_LZ4_CHUNK_SIZE) { - char subChunk = inputOffset + ST_LZ4_CHUNK_SIZE < sizeInBytes; - int64_t bytesWritten = LZ4_compress(((char*)data) + inputOffset, buffer+(outputOffset+1), subChunk ? ST_LZ4_CHUNK_SIZE : sizeInBytes - inputOffset); - *(buffer+outputOffset) = subChunk; - outputOffset += 1+bytesWritten; - assert(outputOffset <= bufferSize); - } - *compressedSizeInBytes = outputOffset; - return st_realloc(buffer, sizeof(char) * outputOffset); -} - -void *stCompression_decompress(void *compressedData, int64_t compressedSizeInBytes, int64_t *sizeInBytes) { - int64_t bufferSize = compressedSizeInBytes * 2 + 1; - char *buffer = st_malloc(sizeof(char) * bufferSize); - int64_t outputOffset=0; - for(int64_t inputOffset=0; inputOffset < compressedSizeInBytes;) { - char subChunk = *(((char *)compressedData)+inputOffset); - inputOffset++; - int64_t outputBufferRemaining = bufferSize - outputOffset; - assert(outputBufferRemaining >= 0); - if(subChunk) { - if(outputBufferRemaining < ST_LZ4_CHUNK_SIZE) { - bufferSize += ST_LZ4_CHUNK_SIZE - outputBufferRemaining; - buffer = st_realloc(buffer, sizeof(char) * bufferSize); - } - int64_t bytesRead = LZ4_uncompress(((char *)compressedData)+inputOffset, - buffer + outputOffset, ST_LZ4_CHUNK_SIZE); - if(bytesRead < 0) { - stThrowNew(ST_COMPRESSION_EXCEPTION_ID, "Tried to uncompress a full length chunk but got a negative return value from lz4_uncompress"); - } - inputOffset += bytesRead; - outputOffset += ST_LZ4_CHUNK_SIZE; - } - else { - int64_t compressedLength = compressedSizeInBytes - inputOffset; - assert(compressedLength < ST_LZ4_CHUNK_SIZE); - while(1) { - int64_t bytesWritten = LZ4_uncompress_unknownOutputSize(((char *)compressedData)+inputOffset, - buffer + outputOffset, compressedLength, outputBufferRemaining < ST_LZ4_CHUNK_SIZE ? outputBufferRemaining : ST_LZ4_CHUNK_SIZE); - if(bytesWritten >= 0 && bytesWritten <= outputBufferRemaining) { - outputOffset += bytesWritten; - break; - } - assert(outputBufferRemaining < ST_LZ4_CHUNK_SIZE); - bufferSize = bufferSize < ST_LZ4_CHUNK_SIZE-outputBufferRemaining ? bufferSize*2 : bufferSize + ST_LZ4_CHUNK_SIZE-outputBufferRemaining; - buffer = st_realloc(buffer, sizeof(char) * bufferSize); - outputBufferRemaining = bufferSize - outputOffset; - } - inputOffset += compressedLength; - } - } - *sizeInBytes = outputOffset; - return st_realloc(buffer, sizeof(char) * outputOffset); -} - -#define Z_CHUNK 262144 - -void *stCompression_compressZlib(void *data, int64_t sizeInBytes, int64_t *compressedSizeInBytes, int64_t level) { - /* - * The internals using the deflate command to avoid buffer overflows. - */ - if(level == -1) { //Use fast compression by default - level = 1; - } - - /* output buffer */ - int64_t bufferSize = sizeInBytes + sizeInBytes/16 + 68; - unsigned char *buffer = st_malloc(sizeof(unsigned char) * bufferSize); - - /* allocate deflate state */ - z_stream strm; - int flush; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - int64_t ret = deflateInit(&strm, level); - if (ret != Z_OK) { - stThrowNew(ST_COMPRESSION_EXCEPTION_ID, "Tried to compress a string but couldn't initialise zlib"); - } - - /* loop compressing */ - int64_t inputOffset=0; - int64_t outputOffset=0; - do { - //This is the inputs - int64_t remainingInput = sizeInBytes - inputOffset; - if(Z_CHUNK >= remainingInput) { - strm.avail_in = remainingInput; - flush = Z_FINISH; - } - else { - strm.avail_in = Z_CHUNK; - flush = Z_NO_FLUSH; - } - strm.next_in = ((unsigned char *)data) + inputOffset; - inputOffset += strm.avail_in; - do { /*Compress to output buffer until the chunk is used up.*/ - //Setup the output buffer - int64_t remainingOutputBuffer = bufferSize - outputOffset; - if(remainingOutputBuffer == 0) { //resize the buffer - bufferSize = bufferSize * 1.5; - st_logDebug("Resizing compression buffer to %" PRIi64 " bytes\n", bufferSize); - buffer = st_realloc(buffer, sizeof(unsigned char) *bufferSize); - } - strm.avail_out = Z_CHUNK < remainingOutputBuffer ? Z_CHUNK : remainingOutputBuffer; - int64_t outputAvailble = strm.avail_out; - strm.next_out = buffer + outputOffset; - //Now do the actual compression - ret = deflate(&strm, flush); /* no bad return value */ - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - outputOffset += outputAvailble - strm.avail_out; /*update the output buffer offset*/ - } while(strm.avail_out == 0); - assert(strm.avail_in == 0); - } while(inputOffset < sizeInBytes); - assert(inputOffset == sizeInBytes); - assert(flush); - //Now set the compressed size - *compressedSizeInBytes = outputOffset; - (void)deflateEnd(&strm); - return st_realloc(buffer, outputOffset); -} - -void *stCompression_decompressZlib(void *compressedData, int64_t compressedSizeInBytes, int64_t *sizeInBytes) { - /* - * Decompresses the compressed data string, which has length compressedSizeInBytes, initialises the sizeInBytes point to the size - * of the decompressed string. - */ - /* output buffer */ - int64_t bufferSize = compressedSizeInBytes * 2; - unsigned char *buffer = st_malloc(sizeof(unsigned char) *bufferSize); - - /* allocate deflate state */ - z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - int64_t ret = inflateInit(&strm); - if (ret != Z_OK) { - stThrowNew(ST_COMPRESSION_EXCEPTION_ID, "Tried to decompress a string but couldn't initialise zlib"); - } - - /* loop compressing */ - int64_t inputOffset=0; - int64_t outputOffset=0; - do { - //This is the inputs - int64_t remainingInput = compressedSizeInBytes - inputOffset; - strm.avail_in = Z_CHUNK >= remainingInput ? remainingInput : Z_CHUNK; - if (strm.avail_in == 0) { - break; - } - strm.next_in = ((unsigned char *)compressedData) + inputOffset; - inputOffset += strm.avail_in; - do { /*Decompress to output buffer until the chunk is used up.*/ - //Setup the output buffer - int64_t remainingOutputBuffer = bufferSize - outputOffset; - if(remainingOutputBuffer == 0) { //resize the buffer - bufferSize = bufferSize * 2; - st_logDebug("Resizing decompression buffer to %" PRIi64 " bytes\n", bufferSize); - buffer = st_realloc(buffer, sizeof(unsigned char) * bufferSize); - } - strm.avail_out = Z_CHUNK < remainingOutputBuffer ? Z_CHUNK : remainingOutputBuffer; - int64_t outputAvailble = strm.avail_out; - strm.next_out = buffer + outputOffset; - //Now do the actual compression - ret = inflate(&strm, Z_NO_FLUSH); /* no bad return value */ - assert(ret != Z_STREAM_ERROR); - if(ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) { - stThrowNew(ST_COMPRESSION_EXCEPTION_ID, "Error %" PRIi64 " in decompressing string of size %" PRIi64 " bytes\n", ret, compressedSizeInBytes); - } - outputOffset += outputAvailble - strm.avail_out; /*update the output buffer offset*/ - } while(strm.avail_out == 0); - assert(strm.avail_in == 0); - } while(inputOffset < compressedSizeInBytes); - assert(inputOffset == compressedSizeInBytes); - //Now set the compressed size - *sizeInBytes = outputOffset; - (void)inflateEnd(&strm); - return st_realloc(buffer, outputOffset); -} diff --git a/C/impl/sonLibConnectivity.c b/C/impl/sonLibConnectivity.c deleted file mode 100644 index 127cb25..0000000 --- a/C/impl/sonLibConnectivity.c +++ /dev/null @@ -1,783 +0,0 @@ -// Dynamically keeps track of the connected components in an -// undirected graph. Adapted from the implementation at www.github.com/sambayless/monosat. The algorithm was -// described by Mikkel Thorup in "Near-optimal Fully Dynamic Graph Connectivity", 2001. -// -// The graph has log(n_nodes) levels, and each edge in the graph is assigned a level, starting at level -// (n_levels - 1) when the edge is added. On each level i, a spanning forest is maintained using edges of -// level at least i. The spanning forest is represented by an Euler Tour tree of the graph. The Euler Tour -// tree represents a tour of the graph by a balanced binary search tree of the edges. -#include "sonLibGlobalsInternal.h" -#include - - -//Public data structures - -struct _stConnectivity { - // Data structure keeping track of the nodes, edges, and connected - // components. - stSet *nodes; - int nNodes; - int nEdges; - stList *et; //list of the Euler Tour Trees for each level in the graph - int nLevels; - stHash *connectedComponents; // Keyed by Euler tour root - - //stores every edge in the graph. Each edge object stores the level of the edge and - //whether or not it's in the spanning forest. For nodes a and b, the edge object is stored - //in either (a, b) or (b, a), but not both. Both possibilities are checked when getting the - //edge. - stEdgeContainer *edges; - - void (*creationCallback)(void *, stConnectedComponent *); - void *creationExtraData; - void (*mergeCallback)(void *, stConnectedComponent *, stConnectedComponent *); - void *mergeExtraData; - void (*cleaveCallback)(void *, stConnectedComponent *, stConnectedComponent *, stSet *); - void *cleaveExtraData; - void (*deletionCallback)(void *, stConnectedComponent *); - void *deletionExtraData; - -}; - -struct _stConnectedComponent { - // Data structure representing a connected component. - void *nodeInComponent; //the root node of the tour - stConnectivity *connectivity; - -}; - -struct _stConnectedComponentIterator { - // Iterator data structure for components in the graph. - stList *componentList; - stEulerTourComponentIterator *compIt; - stConnectivity *connectivity; -}; - -struct _stConnectedComponentNodeIterator { - // Iterator for nodes in a component - - //set of the nodes that have already been visited in the Euler Tour. The Euler Tour visits each node - //at least twice, but the iterator should only return each node once. - stSet *seen; - - //Euler Tour iterator for this connected component on the top level. - stEulerTourIterator *tourIterator; -}; -//Private data structures----------------------------------- -struct DynamicEdge { - void *edgeID; - void *from; - void *to; - - //whether or not this edge is part of the spanning forest on the top level. - bool in_forest; - - //lower level edges are checked first when searching for a replacement edge. - //Changing the levels of edges appropriately saves time when removing future edges. - int level; - - // The number of copies of this edge that exist in the graph. - int multiplicity; -}; -//private methods------------------------------------------- -struct DynamicEdge *DynamicEdge_construct() { - struct DynamicEdge *edge = st_malloc(sizeof(struct DynamicEdge)); - edge->from = NULL; - edge->to = NULL; - edge->in_forest = false; - edge->level = 0; - edge->multiplicity = 1; - return(edge); -} -void DynamicEdge_increment(struct DynamicEdge *edge) { - edge->multiplicity++; -} -void DynamicEdge_decrement(struct DynamicEdge *edge) { - edge->multiplicity--; -} -int DynamicEdge_multiplicity(struct DynamicEdge *edge) { - return edge->multiplicity; -} -void DynamicEdge_destruct(struct DynamicEdge *edge) { - free(edge); -} -stEulerTour *getTopLevel(stConnectivity *connectivity) { - return stList_get(connectivity->et, 0); -} - -//add new levels to compensate for the addition of new nodes, -//and copy nodes from level 0 to the new levels so that all -//levels have the same nodes -void addLevel(stConnectivity *connectivity) { - - stEulerTour *newLevel = stEulerTour_construct(); - stSetIterator *it = stSet_getIterator(connectivity->nodes); - void *node; - while((node = stSet_getNext(it))) { - stEulerTour_createVertex(newLevel, node); - } - stList_append(connectivity->et, newLevel); - stSet_destructIterator(it); -} -void removeLevel(stConnectivity *connectivity) { - stEulerTour *top = stList_pop(connectivity->et); - stEulerTour_destruct(top); -} -void resizeIncidentEdgeList(stList *incident, int newsize) { - for(int i = newsize; i < stList_length(incident); i++) { - stList_remove(incident, newsize); - } -} -int getNLevels(int nNodes) { - return (int) ((int)(log(nNodes)/log(2)) + 1); -} - -// Exported methods ---------------------------------------------------------------------- - -stConnectivity *stConnectivity_construct(void) { - // Initialize the data structure with an empty graph with 0 nodes. - stConnectivity *connectivity = st_malloc(sizeof(stConnectivity)); - connectivity->nodes = stSet_construct(); - - connectivity->et = stList_construct3(0, (void(*)(void*))stEulerTour_destruct); - - //add level zero Euler Tour - stList_append(connectivity->et, stEulerTour_construct()); - connectivity->connectedComponents = stHash_construct2(NULL, - (void(*)(void*))stConnectedComponent_destruct); - - - connectivity->nLevels = 0; - connectivity->nNodes = 0; - connectivity->nEdges = 0; - connectivity->edges = stEdgeContainer_construct((void(*)(void*))DynamicEdge_destruct); - - connectivity->creationCallback = NULL; - connectivity->mergeCallback = NULL; - connectivity->cleaveCallback = NULL; - connectivity->deletionCallback = NULL; - - return(connectivity); - -} - -void stConnectivity_destruct(stConnectivity *connectivity) { - // Free the memory for the data structure. - stList_destruct(connectivity->et); - stSet_destruct(connectivity->nodes); - stEdgeContainer_destruct(connectivity->edges); - stHash_destruct(connectivity->connectedComponents); - - free(connectivity); -} - - - -void stConnectivity_addNode(stConnectivity *connectivity, void *node) { - // Add an isolated node to the graph. This should end up in a new - // connected component with only one member. - connectivity->nNodes++; - - //maintain log(n) levels in the graph - int nLevels = getNLevels(connectivity->nNodes); - if (nLevels > connectivity->nLevels) { - // We never shrink the number of levels in the graph, - // to avoid pathological cases where an entire level - // needs to be added/deleted several times in succession. - connectivity->nLevels = nLevels; - } - while(stList_length(connectivity->et) < connectivity->nLevels) { - addLevel(connectivity); - } - - - stSet_insert(connectivity->nodes, node); - - - for(int i = 0; i < connectivity->nLevels; i++) { - //Add a new disconnected node to the Euler tour on level i - stEulerTour *et_i = stList_get(connectivity->et, i); - stEulerTour_createVertex(et_i, node); - } - - if (connectivity->creationCallback) { - connectivity->creationCallback(connectivity->creationExtraData, stConnectivity_getConnectedComponent(connectivity, node)); - } -} - -bool stConnectivity_hasEdge(stConnectivity *connectivity, void *node1, void *node2) { - return stEdgeContainer_hasEdge(connectivity->edges, node1, node2); -} - -void stConnectivity_addEdge(stConnectivity *connectivity, void *node1, void *node2) { - assert(node1 != node2); - struct DynamicEdge *edge = stEdgeContainer_getEdge(connectivity->edges, node1, node2); - if (edge != NULL) { - // This edge is already present in the graph--just increment the multiplicity. - DynamicEdge_increment(edge); - return; - } - connectivity->nEdges++; - struct DynamicEdge *newEdge = DynamicEdge_construct(); - - newEdge->from = node1; - newEdge->to = node2; - - newEdge->level = 0; - - //add the edge object as an incident edge to an arbitrary one of the nodes - stEdgeContainer_addEdge(connectivity->edges, node1, node2, newEdge); - - - stEulerTour *et_lowest = getTopLevel(connectivity); - if(!stEulerTour_connected(et_lowest, node1, node2)) { - //the two nodes are not already connected, so the new node will be pat of the spanning forest. - //find the two connected components and invalidate them. - stConnectedComponent *component1 = stHash_remove(connectivity->connectedComponents, stEulerTour_getConnectedComponent(et_lowest, node1)); - stConnectedComponent *component2 = stHash_remove(connectivity->connectedComponents, stEulerTour_getConnectedComponent(et_lowest, node2)); - stConnectedComponent_destruct(component1); - //link the level N - 1 Euler Tours together, which corresponds to - //adding a tree edge on level N - 1. - stEulerTour_link(et_lowest, node1, node2); - newEdge->in_forest = true; - - if (component2) { - component2->nodeInComponent = stEulerTour_getConnectedComponent(et_lowest, node1); - stHash_insert(connectivity->connectedComponents, component2->nodeInComponent, component2); - if (connectivity->mergeCallback) { - connectivity->mergeCallback(connectivity->mergeExtraData, component1, component2); - } - } - } - else { - //the nodes were already connected, so the Euler tour doesn't need - //to be updated, and the edge is not part of the spanning forest. - newEdge->in_forest = false; - } - return; - -} - -int stConnectivity_getNComponents(stConnectivity *connectivity) { - stEulerTour *topLevel = getTopLevel(connectivity); - return stEulerTour_getNComponents(topLevel); -} - -int stConnectivity_connected(stConnectivity *connectivity, void *node1, void *node2) { - //check whether node1 and node2 have the same root in the spanning forest - //on level N - 1. - stEulerTour *et_lowest = getTopLevel(connectivity); - return(stEulerTour_connected(et_lowest, node1, node2)); -} -stEdgeContainer *stConnectivity_getEdges(stConnectivity *connectivity) { - return connectivity->edges; -} - -void print_list(stList *list) { - stListIterator *it = stList_getIterator(list); - void *item; - while((item = stList_getNext(it))) { - printf("%p ", item); - } - stList_destructIterator(it); - printf("\n"); -} - - -//Attempts to find a replacement edge connecting two nodes, after a tree edge has been deleted. -//Searches the edges incident to node w for such a replacement edge. -struct DynamicEdge *visit(stConnectivity *connectivity, void *w, void *otherTreeVertex, - struct DynamicEdge *removedEdge, int level, stSet *seen) { - - if(stSet_search(seen, w)) { - return(NULL); - } - stSet_insert(seen, w); - - //get a list of all edges incident to node w, which are possible replacement tree edges. - stList *w_incident = stEdgeContainer_getIncidentEdgeList(connectivity->edges, w); - int w_incident_length = stList_length(w_incident); - - int k, j = 0; - - stEulerTour *et_level = stList_get(connectivity->et, level); - for(k = 0; k < w_incident_length; k++) { - void *e_wk_node2 = stList_get(w_incident, k); - struct DynamicEdge *e_wk = stEdgeContainer_getEdge(connectivity->edges, - w, e_wk_node2); - if (e_wk == removedEdge || e_wk->in_forest) { - //This edge won't work because it's either already in the forest, - //or the edge that we're trying to replace. - continue; - } - if (e_wk->level == level) { - - //Get e_wk's other node (not w) - void *otherNode = e_wk->from == w ? e_wk->to: e_wk->from; - if (stEulerTour_connected(et_level, otherTreeVertex, otherNode)) { - //e_wk connects the two components, so it is the desired replacement - //edge. - for(k = k+1; k < w_incident_length; k++) { - struct DynamicEdge *e_toRemove_node2 = stList_get(w_incident, k); - struct DynamicEdge *e_toRemove = stEdgeContainer_getEdge(connectivity->edges, - w, e_toRemove_node2); - if(e_toRemove == removedEdge || e_toRemove->in_forest) { - continue; - } - stList_set(w_incident, j++, e_toRemove_node2); - - } - stList_destruct(w_incident); - return(e_wk); - } - else { - //the level of this edge can be increased since it does - //not connect to the other component. This leads to later time - //savings because this edge will be tried sooner when searching - //for a lower level replacement edge. Decreasing the level of - //this edge pays for considering it as a replacement. - e_wk->level++; - } - } - stList_set(w_incident, j++, e_wk_node2); - - } - stList_destruct(w_incident); - return(NULL); - -} - -//Remove an edge from the graph and update the connected components. If the edge was -//a tree edge, attempt to find a replacement edge to keep node1 and node2 connected. The -//replacement edge should have the highest possible level. -void stConnectivity_removeEdge(stConnectivity *connectivity, void *node1, void *node2) { - struct DynamicEdge *edge = stEdgeContainer_getEdge(connectivity->edges, - node1, node2); - assert(edge); - DynamicEdge_decrement(edge); - if(DynamicEdge_multiplicity(edge) > 0) { - // There's still a copy of this edge in the multigraph. - return; - } - if(!edge->in_forest) { - stEdgeContainer_deleteEdge(connectivity->edges, node1, node2); - - return; - } - - stConnectedComponent *previousComponent = stHash_search(connectivity->connectedComponents, - stEulerTour_getConnectedComponent(getTopLevel(connectivity), node1)); - - assert(edge->level < connectivity->nLevels - 1); - for (int i = edge->level + 1; i < connectivity->nLevels; i++) { - assert(!stEulerTour_connected(stList_get(connectivity->et, i), node1, node2)); - } - //stEulerTour *et_top = stConnectivity_getTopLevel(connectivity); - //assert(stEulerTour_connected(et_top, node1, node2)); - - struct DynamicEdge *replacementEdge = NULL; - for (int i = edge->level; !replacementEdge && i >= 0; i--) { - stSet *seen = stSet_construct(); - stEulerTour *et_i = stList_get(connectivity->et, i); - assert(stEulerTour_connected(et_i, node1, node2)); - - assert(stEulerTour_hasEdge(et_i, node1, node2) == stEulerTour_hasEdge(et_i, node2, node1)); - assert(stEulerTour_hasEdge(et_i, node1, node2)); - stEulerTour_cut(et_i, node1, node2); - - //set node1 equal to id of the vertex in the smaller of the two components that have just - //been created by deleting the edge - if(stEulerTour_size(et_i, node2) > stEulerTour_size(et_i, node1)) { - void *temp = node1; - node1 = node2; - node2 = temp; - } - //void *smallerComponent = stEulerTour_size(et_i, node2) > stEulerTour_size(et_i, node1) ? node1 : node2; - edge->in_forest = false; - replacementEdge = visit(connectivity, node2, node1, edge, i, seen); - - //go through each edge in the tour on level i - stEulerTourEdgeIterator *edgeIt = stEulerTour_getEdgeIterator(et_i, node2); - void *from = NULL; - void *to = NULL; - while(stEulerTourEdgeIterator_getNext(edgeIt, &from, &to)) { - struct DynamicEdge *treeEdge = stEdgeContainer_getEdge(connectivity->edges, from, to); - assert(treeEdge->in_forest); - if(treeEdge->level == i) { - treeEdge->level++; - assert(treeEdge->level <= connectivity->nLevels - 1); - stEulerTour *et_te = stList_get(connectivity->et, treeEdge->level); - assert(!stEulerTour_connected(et_te, treeEdge->from, treeEdge->to)); - stEulerTour_link(et_te, treeEdge->from, treeEdge->to); - assert(stEulerTour_connected(et_te, treeEdge->from, treeEdge->to)); - } - for (int n = 0; !replacementEdge && n < 2; n++) { - void *w = n ? treeEdge->to : treeEdge->from; - replacementEdge = visit(connectivity, w, node1, edge, i, seen); - } - } - stEulerTourEdgeIterator_destruct(edgeIt); - - if(replacementEdge) { - assert(replacementEdge != edge); - assert(replacementEdge->level == i); - replacementEdge->in_forest = true; - - stEulerTour_link(et_i, replacementEdge->from, replacementEdge->to); - for(int h = replacementEdge->level - 1; h >= 0; h--) { - stEulerTour *et_h = stList_get(connectivity->et, h); - assert(stEulerTour_hasEdge(et_h, node1, node2)); - stEulerTour_cut(et_h, node1, node2); - assert(!stEulerTour_connected(et_h, node1, node2)); - stEulerTour_link(et_h, replacementEdge->from, replacementEdge->to); - } - } - stSet_destruct(seen); - } - if (previousComponent) { - //update the component to use the new root - stHash_remove(connectivity->connectedComponents, previousComponent->nodeInComponent); - previousComponent->nodeInComponent = stEulerTour_getConnectedComponent(getTopLevel(connectivity), node1); - stHash_insert(connectivity->connectedComponents, previousComponent->nodeInComponent, previousComponent); - if (!replacementEdge && connectivity->cleaveCallback) { - stConnectedComponent *newComponent = stConnectivity_getConnectedComponent(connectivity, node2); - stSet *newVertices = stSet_construct(); - stConnectedComponentNodeIterator *it = stConnectedComponent_getNodeIterator(newComponent); - void *vertex; - while ((vertex = stConnectedComponentNodeIterator_getNext(it)) != NULL) { - stSet_insert(newVertices, vertex); - } - connectivity->cleaveCallback(connectivity->cleaveExtraData, previousComponent, newComponent, newVertices); - stSet_destruct(newVertices); - stConnectedComponentNodeIterator_destruct(it); - } - } - stEdgeContainer_deleteEdge(connectivity->edges, node1, node2); - return; - -} - -// Might be cool to be able to add or remove several edges at once, if there is a way to -// make that more efficient than adding them one at a time. Depends on the details of -// the algorithm you use. - -void stConnectivity_removeNode(stConnectivity *connectivity, void *node) { - // Remove a node (and all its edges) from the graph. - stList *nodeIncident = stEdgeContainer_getIncidentEdgeList(connectivity->edges, node); - stListIterator *it = stList_getIterator(nodeIncident); - void *node2; - while((node2 = stList_getNext(it))) { - // Work around the fact that edges can have multiple copies. - while (stConnectivity_hasEdge(connectivity, node, node2)) { - stConnectivity_removeEdge(connectivity, node, node2); - } - } - stList_destructIterator(it); - stList_destruct(nodeIncident); - stSet_remove(connectivity->nodes, node); - - connectivity->nNodes--; - //delete a level if necessary to preserve log(n) levels - // Temporarily disabled since with the removal of enough - // nodes, there can be cases where some edges still have a - // higher level than the graph has. - - // connectivity->nLevels = getNLevels(connectivity->nNodes); - // if(connectivity->nLevels < stList_length(connectivity->et)) { - // removeLevel(connectivity); - // } - - if (connectivity->deletionCallback) { - connectivity->deletionCallback(connectivity->deletionExtraData, stConnectivity_getConnectedComponent(connectivity, node)); - } - - stConnectedComponent_destruct(stHash_remove(connectivity->connectedComponents, node)); - - for(int i = 0; i < connectivity->nLevels; i++) { - stEulerTour *et_i = stList_get(connectivity->et, i); - stEulerTour_removeVertex(et_i, node); - } - -} - -void stConnectivity_setCreationCallback(stConnectivity *connectivity, void (*callback)(void *, stConnectedComponent *), void *extraData) { - connectivity->creationCallback = callback; - connectivity->creationExtraData = extraData; -} - -void stConnectivity_setMergeCallback(stConnectivity *connectivity, void (*callback)(void *, stConnectedComponent *, stConnectedComponent *), void *extraData) { - connectivity->mergeCallback = callback; - connectivity->mergeExtraData = extraData; -} - -void stConnectivity_setCleaveCallback(stConnectivity *connectivity, void (*callback)(void *, stConnectedComponent *, stConnectedComponent *, stSet *), void *extraData) { - connectivity->cleaveCallback = callback; - connectivity->cleaveExtraData = extraData; -} - -void stConnectivity_setDeletionCallback(stConnectivity *connectivity, void (*callback)(void *, stConnectedComponent *), void *extraData) { - connectivity->deletionCallback = callback; - connectivity->deletionExtraData = extraData; -} - -stConnectedComponent *stConnectedComponent_construct(stConnectivity *connectivity, void *node) { - stConnectedComponent *component = st_malloc(sizeof(stConnectedComponent)); - component->nodeInComponent = node; - component->connectivity = connectivity; - return(component); -} - -stConnectedComponent *stConnectivity_getConnectedComponent(stConnectivity *connectivity, - void *node) { - // Get the connected component that this node is a member of. If - // the component is modified, this pointer can be invalidated - stEulerTour *et_0 = getTopLevel(connectivity); - void *compNode = stEulerTour_getConnectedComponent(et_0, node); - stConnectedComponent *comp; - if ((comp = stHash_search(connectivity->connectedComponents, compNode)) == NULL) { - comp = stConnectedComponent_construct(connectivity, compNode); - stHash_insert(connectivity->connectedComponents, compNode, comp); - } - return comp; -} -void *stConnectedComponent_getNodeInComponent(stConnectedComponent *component) { - return(component->nodeInComponent); -} - -stConnectedComponentNodeIterator *stConnectedComponent_getNodeIterator(stConnectedComponent - *component) { - // Get an iterator over the nodes in a particular connected - // component. You can safely assume that the graph won't be - // modified while this iterator is active. - stConnectedComponentNodeIterator *it = st_malloc(sizeof(stConnectedComponentNodeIterator)); - stEulerTour *et = getTopLevel(component->connectivity); - it->seen = stSet_construct(); - it->tourIterator = stEulerTour_getIterator(et, component->nodeInComponent); - return(it); -} - -void *stConnectedComponentNodeIterator_getNext(stConnectedComponentNodeIterator *it) { - // Return the next node of the connected component, or NULL if all have been traversed. - //void *currentNode = it->currentNode; - void *currentNode = stEulerTourIterator_getNext(it->tourIterator); - - if(stSet_search(it->seen, currentNode)) { - return(stConnectedComponentNodeIterator_getNext(it)); - } - stSet_insert(it->seen, currentNode); - return(currentNode); - -} - -void stConnectedComponentNodeIterator_destruct(stConnectedComponentNodeIterator *it) { - // Free the iterator data structure. - stSet_destruct(it->seen); - stEulerTourIterator_destruct(it->tourIterator); - free(it); -} - -stConnectedComponentIterator *stConnectivity_getConnectedComponentIterator(stConnectivity *connectivity) { - // Get an iterator over the connected components in the - // graph. Again, if the graph is modified while the iterator is - // active, it's ok for it to break. - stConnectedComponentIterator *it = st_malloc(sizeof(stConnectedComponentIterator)); - it->componentList = stList_construct3(0, (void(*)(void*))stConnectedComponent_destruct); - - stEulerTour *et_0 = getTopLevel(connectivity); - it->compIt = stEulerTour_getComponentIterator(et_0); - it->connectivity = connectivity; - return(it); -} - -stConnectedComponent *stConnectedComponentIterator_getNext(stConnectedComponentIterator *it) { - // Return the next connected component in the graph, or NULL if all have been traversed. - void *nextNode = stEulerTourComponentIterator_getNext(it->compIt); - if(!nextNode) return NULL; - stConnectedComponent *next = stConnectedComponent_construct(it->connectivity, nextNode); - stList_append(it->componentList, next); - return(next); -} - -void stConnectedComponentIterator_destruct(stConnectedComponentIterator *it) { - // Free the iterator data structure. - stEulerTourComponentIterator_destruct(it->compIt); - stList_destruct(it->componentList); - free(it); -} -void stConnectedComponent_destruct(stConnectedComponent *comp) { - free(comp); -} -//--------------------------------------------------------------------------------------------------------- -struct _stEdgeContainer { - stHash *edges; - stSet *edgeObjects; - void(*destructEdge)(void *); - -}; -struct linkedListNode { - struct linkedListNode *next; - struct linkedListNode *prev; - void *key; - void *value; -}; -struct linkedList { - struct linkedListNode *head; -}; -struct linkedList *linkedList_construct() { - struct linkedList *list = st_malloc(sizeof(struct linkedList)); - list->head = NULL; - return list; -} -void linkedList_destruct(struct linkedList *list) { - struct linkedListNode *node = list->head; - if(!node) { - free(list); - return; - } - while(node->next) { - node = node->next; - free(node->prev); - } - free(node); - free(list); -} -struct linkedListNode *linkedListNode_construct(void *key, void *value) { - struct linkedListNode *node = st_malloc(sizeof(struct linkedListNode)); - node->next = NULL; - node->prev = NULL; - node->key = key; - node->value = value; - return node; -} -void *linkedList_search(struct linkedList *list, void *key) { - struct linkedListNode *node = list->head; - while(node) { - if(node->key == key) { - return node->value; - } - node = node->next; - } - return NULL; -} -void linkedList_delete(struct linkedList *list, void *key) { - struct linkedListNode *node = list->head; - while(node) { - if(node->key == key) break; - node = node->next; - } - if(!node) return; - if(node->prev) node->prev->next = node->next; - if(node->next) node->next->prev = node->prev; - if(!node->prev) { - list->head = node->next; - } - free(node); -} -void linkedList_insert(struct linkedList *list, void *key, void *value) { - struct linkedListNode *new = linkedListNode_construct(key, value); - if(!list->head) { - list->head = new; - return; - } - struct linkedListNode *node = list->head; - while(node->next) { - node = node->next; - } - node->next = new; - new->prev = node; - new->next = NULL; -} -stList *linkedList_toList(struct linkedList *oldList) { - stList *newList = stList_construct(); - struct linkedListNode *node = oldList->head; - while(node) { - stList_append(newList, node->key); - node = node->next; - } - return newList; -} - -stEdgeContainer *stEdgeContainer_construct(void(*destructEdge)(void *)) { - stEdgeContainer *container = st_malloc(sizeof(stEdgeContainer)); - container->edges = stHash_construct2(NULL, (void(*)(void*))linkedList_destruct); - - container->edgeObjects = stSet_construct2(destructEdge); - container->destructEdge = destructEdge; - return container; -} -void stEdgeContainer_destruct(stEdgeContainer *container) { - stHash_destruct(container->edges); - stSet_destruct(container->edgeObjects); - free(container); -} -void *stEdgeContainer_getEdge(stEdgeContainer *container, void *u, void *v) { - struct linkedList *u_incident = stHash_search(container->edges, u); - if(!u_incident) return NULL; - return linkedList_search(u_incident, v); -} -void stEdgeContainer_deleteEdge(stEdgeContainer *container, void *u, void *v) { - void *edge = stEdgeContainer_getEdge(container, u, v); - struct linkedList *u_incident = stHash_search(container->edges, u); - linkedList_delete(u_incident, v); - struct linkedList *v_incident = stHash_search(container->edges, v); - linkedList_delete(v_incident, u); - void *edgeObject = stSet_remove(container->edgeObjects, edge); - container->destructEdge(edgeObject); -} -bool stEdgeContainer_hasEdge(stEdgeContainer *container, void *u, void *v) { - struct linkedList *u_incident = stHash_search(container->edges, u); - if(!u_incident) return false; - if(linkedList_search(u_incident, v)) return true; - return false; -} - -void stEdgeContainer_addEdge(stEdgeContainer *container, void *u, void *v, void *edge) { - struct linkedList *u_incident = stHash_search(container->edges, u); - if(!u_incident) { - u_incident = linkedList_construct(); - stHash_insert(container->edges, u, u_incident); - } - linkedList_insert(u_incident, v, edge); - struct linkedList *v_incident = stHash_search(container->edges, v); - if(!v_incident) { - v_incident = linkedList_construct(); - stHash_insert(container->edges, v, v_incident); - } - linkedList_insert(v_incident, u, edge); - - stSet_insert(container->edgeObjects, edge); -} -stList *stEdgeContainer_getIncidentEdgeList(stEdgeContainer *container, void *v) { - struct linkedList *vincident = stHash_search(container->edges, v); - if(!vincident) return stList_construct(); - return linkedList_toList(vincident); -} - -struct _stEdgeContainerIterator { - stHashIterator *nodeIterator; - struct linkedListNode *node; - stEdgeContainer *container; -}; -stEdgeContainerIterator *stEdgeContainer_getIterator(stEdgeContainer *container) { - stEdgeContainerIterator *it = st_malloc(sizeof(stEdgeContainerIterator)); - it->nodeIterator = stHash_getIterator(container->edges); - it->container = container; - it->node = NULL; - return it; -} -bool stEdgeContainer_getNext(stEdgeContainerIterator *it, void **node1, void **node2) { - if(!it->node) { - *node1 = stHash_getNext(it->nodeIterator); - struct linkedList *nextList = stHash_search(it->container->edges, *node1); - if(!nextList) return false; - it->node = nextList->head; - } - if(!it->node) return false; - *node2 = it->node->key; - it->node = it->node->next; - return true; -} -void stEdgeContainer_destructIterator(stEdgeContainerIterator *it) { - stHash_destructIterator(it->nodeIterator); - free(it); -} diff --git a/C/impl/sonLibEulerTour.c b/C/impl/sonLibEulerTour.c deleted file mode 100644 index 4face31..0000000 --- a/C/impl/sonLibEulerTour.c +++ /dev/null @@ -1,731 +0,0 @@ -#include "sonLibGlobalsInternal.h" - - -/*represents the Euler Tour Tree of an undirected graph. The Euler Tour - * is stored in a balanced binary tree where each node in the BST represents one - * traversal of an edge - * in the graph, and the nodes are ordered by their traversal time on the Euler tour. - * Each edge in the graph is traversed exactly twice. - * - * Graph: - * y z - * C--------D-------E - * / \ / - * w/ \x /u - * / \ v / - * A B--------F - * - * Euler tour: wxvvxyzzyw - * - * Balanced Euler tour tree of the edges, keyed by traversal order in the Euler tour: - * (y,6) - * / \ - * / \ - * / \ - * (v,4) (z,8) - * / \ / \ - * / \ / \ - * (x,2) (x,5) (z,7) (w,10) - * / \ / - * / \ / - * (w,1) (v,3) (y,9) - * - * - * Graph representation: - * V_right_in ____ W_right_in ___ - *tour end ...<---------- | |<-----------| |<--------- - * | V | | W | - *tour start ...---------> |____|----------->|___|---------> - * V_left_out W_left_out - * - * Undirected edges are represented as two directed half-edges. - */ - -struct _stEulerVertex { - stEulerHalfEdge *leftOut; //first time this vertex is visited in tour - stEulerHalfEdge *rightIn; //second time vertex is visited - stEulerTour *owner; - - void *vertexID; //index into the Euler Tree's hashtable of vertices -}; - -struct _stEulerHalfEdge { - int isForwardEdge; - - stEulerVertex *from; - stEulerVertex *to; - stEulerHalfEdge *inverse; - - //node in treap for this half-edge. - stTreap *node; - -}; - -struct _stEulerTour { - stHash *vertices; - stEdgeContainer *edges; - stSet *connectedComponents; - - int nComponents; -}; -struct _stEulerTourIterator { - void *currentVertex; - stTreap *currentEdgeNode; -}; -struct _stEulerTourEdgeIterator { - stTreap *currentEdgeNode; -}; -struct _stEulerTourComponentIterator { - stSetIterator *it; -}; - - -/*Euler Vertex methods ----------------------------------------------------- */ - - -stEulerVertex *stEulerVertex_construct(void *vertexID) { - stEulerVertex *v = st_malloc(sizeof(stEulerVertex)); - v->vertexID = vertexID; - v->leftOut = NULL; - v->rightIn = NULL; - return(v); -} -void stEulerVertex_destruct(stEulerVertex *vertex) { - free(vertex); -} -/*Returns the half-edge coming into this vertex on the first traversal.*/ -stTreap *stEulerVertex_incidentEdgeA(stEulerVertex *vertex) { - if(vertex->leftOut) { - return(vertex->leftOut->node); - } - else { - return(NULL); - } -} -/*Returns the half edge leaving this vertex on the second traversal. */ -stTreap *stEulerVertex_incidentEdgeB(stEulerVertex *vertex) { - if(vertex->rightIn) { - return(vertex->rightIn->node); - } - else { - return(NULL); - } -} -int stEulerVertex_connected(stEulerVertex *from, stEulerVertex *to) { - if(from == to) { - return(true); - } - stTreap *fromNode = stEulerVertex_incidentEdgeA(from); - stTreap *toNode = stEulerVertex_incidentEdgeA(to); - if(fromNode == NULL || toNode == NULL) { - return(false); - } - stTreap *a_root = stTreap_findRoot(fromNode); - stTreap *b_root = stTreap_findRoot(toNode); - return(a_root == b_root); -} -int stEulerVertex_isSingleton(stEulerVertex *vertex) { - assert(!vertex->rightIn == !vertex->leftOut); - - return(!(vertex->leftOut)); -} - -/*Euler Half Edge methods ------------------------------------------------- */ -stEulerHalfEdge *stEulerHalfEdge_construct() { - stEulerHalfEdge *newEdge = st_malloc(sizeof(stEulerHalfEdge)); - newEdge->node = stTreap_construct(newEdge); - return newEdge; -} - - -int stEulerHalfEdge_contains(stEulerHalfEdge *edge, stEulerVertex *vertex) { - return (edge->from == vertex || edge->to == vertex); -} -void stEulerHalfEdge_destruct(stEulerHalfEdge *edge) { - if(edge != NULL) { - stTreap_nodeDestruct(edge->node); - } - if(edge->inverse != NULL) { - stTreap_nodeDestruct(edge->inverse->node); - } - free(edge->inverse); - free(edge); -} -void *stEulerHalfEdge_getFrom(stEulerHalfEdge *edge) { - return(edge->from->vertexID); -} -void *stEulerHalfEdge_getTo(stEulerHalfEdge *edge) { - return(edge->to->vertexID); -} - - -/*Euler Tour methods ------------------------------------------------------ */ -stEulerTour *stEulerTour_construct() { - stEulerTour *et = st_malloc(sizeof(stEulerTour)); - - et->vertices = stHash_construct2(NULL, (void(*)(void*))stEulerVertex_destruct); - et->edges = stEdgeContainer_construct((void(*)(void*))stEulerHalfEdge_destruct); - et->connectedComponents = stSet_construct(); - - et->nComponents = 0; - return(et); -} -bool stEulerTour_hasEdge(stEulerTour *et, void *u, void *v) { - return stEdgeContainer_hasEdge(et->edges, u, v); -} -int stEulerTour_getNComponents(stEulerTour *et) { - return stSet_size(et->connectedComponents); -} -stEdgeContainer *stEulerTour_getEdges(stEulerTour *et) { - return et->edges; -} -bool stEulerTour_isSingleton(stEulerTour *et, void *v) { - stEulerVertex *vertex = stEulerTour_getVertex(et, v); - return stEulerVertex_isSingleton(vertex); -} -void stEulerTour_printTour(stEulerTour *et, void *v) { - stEulerTourIterator *it = stEulerTour_getIterator(et, v); - printf("tour: "); - void *node; - while((node = stEulerTourIterator_getNext(it))) { - printf("%p ", node); - } - stEulerTourIterator_destruct(it); - printf("\n"); -} -void stEulerTour_printEdgeTour(stEulerTour *et, void *v) { - stEulerTourEdgeIterator *it = stEulerTour_getEdgeIterator(et, v); - printf("edge tour: "); - void *node1, *node2; - while(stEulerTourEdgeIterator_getNext(it, &node1, &node2)) { - printf("%p->%p ", node1, node2); - } - stEulerTourEdgeIterator_destruct(it); -} - -void stEulerTour_destruct(stEulerTour *et) { - if(et != NULL) { - stHash_destruct(et->vertices); - stEdgeContainer_destruct(et->edges); - stSet_destruct(et->connectedComponents); - free(et); - } -} -stTreap *stEulerTour_findRoot(stEulerTour *et, void *v) { - stEulerVertex *vertex = stEulerTour_getVertex(et, v); - if(!vertex) { - fprintf(stderr, "Warning: vertex does not exist\n"); - return(NULL); - } - stTreap *treapNode = stEulerVertex_incidentEdgeA(vertex); - if(!treapNode) { - return(NULL); - } - return(stTreap_findMin(stTreap_findRoot(treapNode))); -} -void *stEulerTour_findRootNode(stEulerTour *et, void *v) { - stTreap *root = stEulerTour_findRoot(et, v); - stEulerHalfEdge *edge = (stEulerHalfEdge *) stTreap_getValue(root); - return(edge->from->vertexID); -} -int stEulerTour_connected(stEulerTour *et, void *u, void *v) { - stEulerVertex *node1 = stHash_search(et->vertices, u); - stEulerVertex *node2 = stHash_search(et->vertices, v); - return(stEulerVertex_connected(node1, node2)); -} - -/*returns the size of the component that vertex v is in. */ -int stEulerTour_size(stEulerTour *et, void *v) { - stEulerVertex *vertex = stHash_search(et->vertices, v); - if(!vertex->leftOut) { - return(1); - } - - int tour_length = stTreap_size(vertex->leftOut->node); - return (tour_length/2 + 1); -} -stEulerVertex *stEulerTour_getVertex(stEulerTour *et, void *v) { - return(stHash_search(et->vertices, v)); -} -stEulerVertex *stEulerTour_createVertex(stEulerTour *et, void *vertexID) { - stEulerVertex *newVertex = stEulerVertex_construct(vertexID); - newVertex->owner = et; - et->nComponents++; - stSet_insert(et->connectedComponents, vertexID); - stHash_insert(et->vertices, vertexID, newVertex); - return(newVertex); -} -void stEulerTour_removeVertex(stEulerTour *et, void *vertexID) { - assert(stEulerTour_isSingleton(et, vertexID)); //remove all edges before removing the vertex - stEulerVertex *removedVertex = stHash_remove(et->vertices, vertexID); - stEulerVertex_destruct(removedVertex); - stSet_remove(et->connectedComponents, vertexID); - et->nComponents--; -} - -void *stEulerTour_getConnectedComponent(stEulerTour *et, void *nodeInComponent) { - if(stEulerTour_isSingleton(et, nodeInComponent)) { - return nodeInComponent; - } - return stEulerTour_findRootNode(et, nodeInComponent); -} - -/*Move a vertex to the beginning of the tour. */ -void stEulerTour_makeRoot(stEulerTour *et, stEulerVertex *vertex) { - if(stEulerVertex_isSingleton(vertex)) { - return; - } - //update this component's root node in the list of connected components - void *currentRoot = stEulerTour_findRootNode(et, vertex->vertexID); - stSet_remove(et->connectedComponents, currentRoot); - stSet_insert(et->connectedComponents, vertex->vertexID); - - - if(stTreap_size(vertex->leftOut->node) == 2) { - assert(stTreap_findRoot(stEulerVertex_incidentEdgeA(vertex)) == - stTreap_findRoot(stEulerVertex_incidentEdgeB(vertex))); - stTreap *first = stTreap_findMin(stTreap_findRoot(stEulerVertex_incidentEdgeA(vertex))); - stEulerHalfEdge *firstEdge = stTreap_getValue(first); - if(firstEdge->from == vertex) return; - stTreap *second = stTreap_splitAfter(first); - stTreap_concat(second, first); - return; - } - - - stTreap *ftreapNode = stEulerVertex_incidentEdgeA(vertex); - stTreap *btreapNode = stEulerVertex_incidentEdgeB(vertex); - stEulerHalfEdge *f = stTreap_getValue(ftreapNode); - stEulerHalfEdge *b = stTreap_getValue(btreapNode); - assert(f != b); - assert(f); - assert(b); - if(stTreap_compare(f->node, b->node) > 0) { - //swap the pointers to the half edges; - stEulerHalfEdge *temp = f; - f = b; - b = temp; - } - assert(stTreap_compare(f->node, b->node) < 0); - - stEulerVertex *other = (f->to == vertex) ? f->from: f->to; - assert(other != vertex); - - //the next edge traversed in the Euler tour - stTreap *nextNode = stTreap_next(f->node); - stEulerHalfEdge *next = (stEulerHalfEdge *)stTreap_getValue(nextNode); - - if(!stEulerHalfEdge_contains(next, vertex)) { - stTreap *fnodeprev = stTreap_prev(f->node); - - //if the previous node is null, vertex comes first in the tour (is the root) - //so do nothing. - if (!fnodeprev) { - assert(stTreap_findRoot(stEulerVertex_incidentEdgeA(vertex)) == - stTreap_findRoot(stEulerVertex_incidentEdgeB(vertex))); - return; - } - else { - f = stTreap_getValue(fnodeprev); - } - } - else if (stEulerHalfEdge_contains(next, other)) { - stTreap *next_next = stTreap_next(next->node); - if(!next_next) { - next_next = stTreap_prev(f->node); - } - - if (next_next) { - stEulerHalfEdge *next_next_edge = - (stEulerHalfEdge*)stTreap_getValue(next_next); - if(stEulerHalfEdge_contains(next_next_edge, vertex)) { - f = next; - } else { - //node is leaf - } - } - } else { - //next contains node - } - - //f is now guaranteed to be before b in the tour - //assert(stTreap_compare(f->node, b->node) < 0); - stTreap *rightSubtree = stTreap_splitAfter(f->node); - - if(rightSubtree) { - assert(stTreap_findMax(stTreap_findRoot(f->node)) == f->node); - assert(stTreap_findRoot(rightSubtree) != stTreap_findRoot(f->node)); - stTreap_concat(rightSubtree, f->node); - } - assert(stTreap_findMax(stTreap_findRoot(f->node)) == f->node); - assert(stTreap_findRoot(stEulerVertex_incidentEdgeA(vertex)) == - stTreap_findRoot(stEulerVertex_incidentEdgeB(vertex))); -} -void stEulerTour_link(stEulerTour *et, void *u, void *v) { - assert(u != v); - assert(!stEulerTour_connected(et, u, v)); - assert(!stEdgeContainer_hasEdge(et->edges, u, v)); - stEulerVertex *vertex = stHash_search(et->vertices, u); - stEulerVertex *other = stHash_search(et->vertices, v); - et->nComponents--; - - - stEulerHalfEdge *newForwardEdge = stEulerHalfEdge_construct(); - stEulerHalfEdge *newBackwardEdge = stEulerHalfEdge_construct(); - stEdgeContainer_addEdge(et->edges, u, v, newForwardEdge); - - newForwardEdge->isForwardEdge = true; - newBackwardEdge->isForwardEdge = false; - newBackwardEdge->inverse = newForwardEdge; - newForwardEdge->inverse = newBackwardEdge; - - newForwardEdge->from = vertex; - newForwardEdge->to = other; - - newBackwardEdge->from = other; - newBackwardEdge->to = vertex; - - - stEulerTour_makeRoot(et, vertex); - stEulerTour_makeRoot(et, other); - - stSet_remove(et->connectedComponents, stEulerTour_getConnectedComponent(et, vertex->vertexID)); - stSet_remove(et->connectedComponents, stEulerTour_getConnectedComponent(et, other->vertexID)); - - stTreap *f = NULL; - if (stEulerVertex_incidentEdgeA(vertex)) { - f = stTreap_findMin(stTreap_findRoot(stEulerVertex_incidentEdgeA(vertex))); - } - - - stTreap *tleft = NULL; - if (f) { - stTreap_concat(f, newForwardEdge->node); - } - else { - vertex->leftOut = newForwardEdge; - } - if (stEulerVertex_incidentEdgeA(other)) { - assert(stTreap_findRoot(stEulerVertex_incidentEdgeA(other)) == - stTreap_findRoot(stEulerVertex_incidentEdgeB(other))); - stTreap_concat(newForwardEdge->node, other->leftOut->node); - assert(stTreap_findRoot(stEulerVertex_incidentEdgeA(other)) == - stTreap_findRoot(stEulerVertex_incidentEdgeB(other))); - assert(stTreap_findRoot(newForwardEdge->node) == stTreap_findRoot(stEulerVertex_incidentEdgeB(other))); - } - else { - other->leftOut = newForwardEdge; - } - if (stEulerVertex_incidentEdgeB(other)) { - assert(stTreap_findRoot(stEulerVertex_incidentEdgeA(other)) == - stTreap_findRoot(stEulerVertex_incidentEdgeB(other))); - stTreap_concat(other->rightIn->node, newBackwardEdge->node); - assert(stTreap_findRoot(stEulerVertex_incidentEdgeA(other)) == - stTreap_findRoot(newBackwardEdge->node)); - assert(stTreap_findRoot(stEulerVertex_incidentEdgeA(vertex)) == - stTreap_findRoot(newBackwardEdge->node)); - - } - else { - other->rightIn = newBackwardEdge; - stTreap_concat(stEulerVertex_incidentEdgeA(vertex), newBackwardEdge->node); - } - if (tleft) { - stTreap_concat(newBackwardEdge->node, tleft); - vertex->rightIn = stTreap_getValue(tleft); - } - else { - vertex->rightIn = newBackwardEdge; - } - assert(stTreap_findRoot(newForwardEdge->node) == stTreap_findRoot(newBackwardEdge->node)); - stSet_insert(et->connectedComponents, stEulerTour_getConnectedComponent(et, vertex->vertexID)); - assert(stEulerVertex_connected(vertex, other)); - assert(stEulerTour_hasEdge(et, u, v)); - assert(stEulerTour_hasEdge(et, v, u)); -} - - -/*remove an edge from the graph, splitting into two Euler tours. - * - * Graph: - * y1 z1 - * C--------D----------E - * / \ y2 z2 / - * / \ / - * w1/w2 x1\x2 u1/u2 - * / \ v1 / - * A B---------F - * v2 - * - * Euler tour: w1->x1->v1->v2->x2->y1->z1->z2->y2->w2 - * y1 - * / \ - * / \ - * v2 z2 - * / \ / \ - * / \ / \ - * x1 x2 z1 w2 - * / \ / - * / \ / - * w1 v1 y2 - * - * Remove y: - * - * tree1: w1->x1->v1->v2->x2 tree2: w2 - * - * concat(tree1, tree2): w1 x1 v1 v2 x2 w2 - * - * - */ - -void stEulerTour_cut(stEulerTour *et, void *u, void *v) { - et->nComponents++; - stSet_remove(et->connectedComponents, stEulerTour_getConnectedComponent(et, u)); - - //get the two halves of this edge - assert(stEulerTour_connected(et, u, v)); - assert(stEulerTour_hasEdge(et, u, v)); - assert(stEulerTour_hasEdge(et, v, u)); - stEulerHalfEdge *f = stEdgeContainer_getEdge(et->edges, u, v); - assert(f); - stEulerHalfEdge *b = f->inverse; - assert(b->inverse == f); - assert(b->inverse->inverse == b); - stEulerVertex *from = f->from; - stEulerVertex *to = f->to; - - assert(stEulerTour_connected(et, f->from->vertexID, f->to->vertexID)); - assert(stTreap_findRoot(f->node) == stTreap_findRoot(b->node)); - - //f should point to the first half of this edge to be traversed, - //and b should point to the half that is traversed second. - if (stTreap_compare(f->node, b->node) > 0) { - //swap f and b - stEulerHalfEdge *temp = f; - f = b; - b = temp; - } - - - stTreap *p = stTreap_prev(f->node); //p - stTreap *n = stTreap_next(b->node); //n - stTreap *pn = stTreap_next(f->node); //pn - stTreap *nn = stTreap_prev(b->node); //nn - - assert(stTreap_next(nn) == b->node); - - /* p ____ f ____ pn - *tour start ---------->|from|----------->|to |--------> - *tour end <----------|____|<-----------|____|<-------- - * n b nn - * - * - * - * - */ - - //get the part of the tour that happened before reaching the first half of this - //edge and the part that happened after reaching the second half. - stTreap *tree1 = stTreap_splitBefore(f->node); - assert(!tree1 || stTreap_findMax(tree1) == p); - if(tree1) { - assert(stTreap_findRoot(tree1) != stTreap_findRoot(f->node)); - } - stTreap *tree2 = stTreap_splitAfter(b->node); - assert(!tree2 || stTreap_findMin(tree2) == n); - - if (tree1 && tree2) { - stTreap_concat(tree1, tree2); - } - assert(!tree1 || stTreap_findRoot(tree1) != stTreap_findRoot(f->node)); - assert(!tree2 || stTreap_findRoot(tree2) != stTreap_findRoot(b->node)); - assert(!tree1 || stTreap_findRoot(tree1) != stTreap_findRoot(b->node)); - assert(!tree2 || stTreap_findRoot(tree2) != stTreap_findRoot(f->node)); - - assert(pn); - assert(nn); - - //choose new incident edges - if (stEulerHalfEdge_contains(stTreap_getValue(pn), from) && - stEulerHalfEdge_contains(stTreap_getValue(pn), to)) { - - if((n || p) && !(n && p)) { - if (!n) { - n = stTreap_findMin(stTreap_findRoot(p)); - } - else { - p = stTreap_findMax(stTreap_findRoot(n)); - } - assert(n != p); - } - if (n) { - assert(p); - assert(stEulerHalfEdge_contains(stTreap_getValue(n), from) || - stEulerHalfEdge_contains(stTreap_getValue(n), to)); - assert(stEulerHalfEdge_contains(stTreap_getValue(p), from) || - stEulerHalfEdge_contains(stTreap_getValue(p), to)); - if(stEulerHalfEdge_contains(stTreap_getValue(n), from)) { - assert(stEulerHalfEdge_contains(stTreap_getValue(p), from)); - from->leftOut = stTreap_getValue(n); - from->rightIn = stTreap_getValue(p); - to->leftOut = NULL; - to->rightIn = NULL; - } - else { - assert(stEulerHalfEdge_contains(stTreap_getValue(n), to)); - assert(stEulerHalfEdge_contains(stTreap_getValue(p), to)); - to->leftOut = stTreap_getValue(n); - to->rightIn = stTreap_getValue(p); - from->leftOut = NULL; - from->rightIn = NULL; - } - } - else { - //to and from are singletons - from->leftOut = NULL; - from->rightIn = NULL; - to->leftOut = NULL; - to->rightIn = NULL; - } - } - else if (stEulerHalfEdge_contains(stTreap_getValue(pn), from)) { - assert(stEulerHalfEdge_contains(stTreap_getValue(nn), from)); - from->leftOut = stTreap_getValue(pn); - from->rightIn = stTreap_getValue(nn); - if ((n || p) && !(n && p)) { - if(!n) { - n = stTreap_findMin(stTreap_findRoot(p)); - } - else { - p = stTreap_findMax(stTreap_findRoot(n)); - } - assert(n != p); - } - if (n) { - assert(p); - assert(stEulerHalfEdge_contains(stTreap_getValue(n), to)); - assert(stEulerHalfEdge_contains(stTreap_getValue(p), to)); - to->leftOut = stTreap_getValue(n); - to->rightIn = stTreap_getValue(p); - } - else { - //to is a singleton - to->leftOut = NULL; - to->rightIn = NULL; - } - } - else if (stEulerHalfEdge_contains(stTreap_getValue(pn), to)) { - assert(stEulerHalfEdge_contains(stTreap_getValue(nn), to)); - to->leftOut = stTreap_getValue(pn); - to->rightIn = stTreap_getValue(nn); - if( (n || p) && !(n && p)) { - if(!n) { - n = stTreap_findMin(stTreap_findRoot(p)); - } - else { - p = stTreap_findMax(stTreap_findRoot(n)); - } - assert(n != p); - } - if (n) { - assert(p); - assert(stEulerHalfEdge_contains(stTreap_getValue(n), from)); - assert(stEulerHalfEdge_contains(stTreap_getValue(p), from)); - from->leftOut = stTreap_getValue(n); - from->rightIn = stTreap_getValue(p); - } - else { - //to is a singleton - from->leftOut = NULL; - from->rightIn = NULL; - } - } - stTreap *after = stTreap_splitAfter(f->node); - stTreap *before = stTreap_splitBefore(b->node); - if(before) assert(stTreap_next(before) != b->node); - if(after) assert(stTreap_prev(after) != f->node); - - if(stEulerVertex_incidentEdgeA(from) && - (stTreap_size(stEulerVertex_incidentEdgeA(from)) == 1)) { - //from is a singleton - from->leftOut = NULL; - from->rightIn = NULL; - } - if(stEulerVertex_incidentEdgeA(to) && - (stTreap_size(stEulerVertex_incidentEdgeA(to)) == 1)) { - to->leftOut = NULL; - to->rightIn = NULL; - } - assert(stTreap_size(f->node) == 1); - assert(stTreap_size(b->node) == 1); - assert(stTreap_next(f->node) == NULL); - assert(stTreap_prev(f->node) == NULL); - assert(stTreap_next(b->node) == NULL); - assert(stTreap_prev(b->node) == NULL); - stEdgeContainer_deleteEdge(et->edges, u, v); - - stSet_insert(et->connectedComponents, stEulerTour_getConnectedComponent(et, u)); - stSet_insert(et->connectedComponents, stEulerTour_getConnectedComponent(et, v)); -} -//------------------------------------------------------------------ -// Tour iterators -stEulerTourIterator *stEulerTour_getIterator(stEulerTour *et, void *v) { - stEulerTourIterator *it = st_malloc(sizeof(stEulerTourIterator)); - it->currentEdgeNode = stEulerTour_findRoot(et, v); - it->currentVertex = v; - return(it); -} -void *stEulerTourIterator_getNext(stEulerTourIterator *it) { - if(!it->currentEdgeNode) { - void *currentVertex = it->currentVertex; - it->currentVertex = NULL; - return(currentVertex); - } - stEulerHalfEdge *currentEdge = (stEulerHalfEdge *) stTreap_getValue(it->currentEdgeNode); - void *vertexToReturn = currentEdge->from->vertexID; - it->currentVertex = currentEdge->to->vertexID; - - it->currentEdgeNode = stTreap_next(it->currentEdgeNode); - return(vertexToReturn); -} -void stEulerTourIterator_destruct(stEulerTourIterator *it) { - free(it); -} -stSet *stEulerTour_getNodesInComponent(stEulerTour *et, void *v) { - stEulerTourIterator *it = stEulerTour_getIterator(et, v); - stSet *nodes = stSet_construct(); - void *node; - while((node = stEulerTourIterator_getNext(it))) { - stSet_insert(nodes, node); - } - stEulerTourIterator_destruct(it); - return(nodes); -} -stEulerTourEdgeIterator *stEulerTour_getEdgeIterator(stEulerTour *et, void *v) { - stEulerTourEdgeIterator *it = st_malloc(sizeof(stEulerTourEdgeIterator)); - it->currentEdgeNode = stEulerTour_findRoot(et, v); - return(it); -} -bool stEulerTourEdgeIterator_getNext(stEulerTourEdgeIterator *it, void **node1, void **node2) { - if(!it->currentEdgeNode) return false; - stEulerHalfEdge *edgeToReturn = (stEulerHalfEdge *)stTreap_getValue(it->currentEdgeNode); - it->currentEdgeNode = stTreap_next(it->currentEdgeNode); - *node1 = edgeToReturn->from->vertexID; - *node2 = edgeToReturn->to->vertexID; - return true; -} -void stEulerTourEdgeIterator_destruct(stEulerTourEdgeIterator *it) { - free(it); -} -stEulerTourComponentIterator *stEulerTour_getComponentIterator(stEulerTour *et) { - stEulerTourComponentIterator *it = st_malloc(sizeof(stEulerTourComponentIterator)); - it->it = stSet_getIterator(et->connectedComponents); - return it; -} -void *stEulerTourComponentIterator_getNext(stEulerTourComponentIterator *it) { - return(stSet_getNext(it->it)); -} -void stEulerTourComponentIterator_destruct(stEulerTourComponentIterator *it) { - stSet_destructIterator(it->it); - free(it); -} diff --git a/C/impl/sonLibExcept.c b/C/impl/sonLibExcept.c deleted file mode 100644 index 4c8d493..0000000 --- a/C/impl/sonLibExcept.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "sonLibExcept.h" -#include -#include "stSafeC.h" - -/** - * Exception object that is thrown. - * @ingroup stExcept - */ -struct stExcept { - const char *id; /**< symbolic exception id */ - const char *msg; /**< natural-language error message */ - struct stExcept *cause; /**< error stack, NULL if no causing errors */ -}; - -/* - * Exception content Top Of Stack. - * FIXME: should be in thread-local storage. - */ -struct _stExceptContext *_cexceptTOS = NULL; - -stExcept *stExcept_newv(const char *id, const char *msg, va_list args) { - stExcept *except = stSafeCCalloc(sizeof(stExcept)); - except->id = id; - except->msg = stSafeCDynFmtv(msg, args); - return except; -} - -stExcept *stExcept_new(const char *id, const char *msg, ...) { - va_list args; - va_start(args, msg); - stExcept *except = stExcept_newv(id, msg, args); - va_end(args); - return except; -} - -stExcept *stExcept_newCausev(stExcept *cause, const char *id, const char *msg, va_list args) { - stExcept *except = stExcept_newv(id, msg, args); - except->cause = cause; - return except; -} - -stExcept *stExcept_newCause(stExcept *cause, const char *id, const char *msg, ...) { - va_list args; - va_start(args, msg); - stExcept *except = stExcept_newCausev(cause, id, msg, args); - va_end(args); - return except; -} - -void stExcept_free(stExcept *except) { - if (except != NULL) { - if (except->cause != NULL) { - stExcept_free(except->cause); - } - stSafeCFree((char*)except->msg); - stSafeCFree(except); - } -} - -const char* stExcept_getId(const stExcept *except) { - return except->id; -} - -const char* stExcept_getMsg(const stExcept *except) { - return except->msg; -} - -stExcept *stExcept_getCause(const stExcept *except) { - return except->cause; -} - -static void handleUncaught(stExcept *except) { - fflush(stdout); - fprintf(stderr, "Exception: %s: %s\n", except->id, except->msg); - for (stExcept *cause = except->cause; cause != NULL; cause = cause->cause) { - fprintf(stderr, "\tcaused by: %s: %s\n", cause->id, cause->msg); - } - fflush(stderr); - if (getenv("ST_ABORT_UNCAUGHT") != NULL) { - abort(); - } - stSafeCErr("Uncaught exception"); -} - -void stThrow(stExcept *except) { - assert(except != NULL); - if (getenv("ST_ABORT") != NULL) { - // print message and call abort to enter debugger - fprintf(stderr, "Exception: %s: %s\n", except->id, except->msg); - abort(); - } - - if (_cexceptTOS == NULL) { - handleUncaught(except); - } - _cexceptTOS->except = except; - longjmp(_cexceptTOS->env, 1); -} - -void stThrowNew(const char *id, const char *msg, ...) { - va_list args; - va_start(args, msg); - stExcept *except = stExcept_newv(id, msg, args); - va_end(args); - stThrow(except); -} - -void stThrowNewCause(stExcept *cause, const char *id, const char *msg, ...) { - va_list args; - va_start(args, msg); - stExcept *except = stExcept_newCausev(cause, id, msg, args); - va_end(args); - stThrow(except); -} - diff --git a/C/impl/sonLibFile.c b/C/impl/sonLibFile.c deleted file mode 100644 index 0871f5b..0000000 --- a/C/impl/sonLibFile.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibFile.c - * - * Created on: 7 Sep 2010 - * Author: benedictpaten - */ -#include "sonLibGlobalsInternal.h" -#include -#include -#include - -const char *ST_FILE_EXCEPTION = "ST_FILE_EXCEPTION"; - -static int64_t stFile_getLineFromFileP(char **s, int64_t *n, FILE *f) { - register int64_t nMinus1 = ((*n) - 1), i = 0; - - char *s2 = *s; - while (1) { - register int64_t ch = (char) getc(f); - - if (ch == '\r') { - ch = getc(f); - } - - if (i == nMinus1) { - *n = 2 * (*n) + 1; - *s = realloc(*s, (*n + 1) * sizeof(char)); - assert(*s != NULL); - s2 = *s + i; - nMinus1 = ((*n) - 1); - } - - if ((ch == '\n') || (ch == EOF)) { - *s2 = '\0'; - return (feof(f) ? -1 : i); - } else { - *s2 = ch; - s2++; - } - ++i; - } - return 0; -} - -char *stFile_getLineFromFile(FILE *fileHandle) { - int64_t length = 100; - char *cA = st_malloc(length * sizeof(char)); - int64_t i = stFile_getLineFromFileP(&cA, &length, fileHandle); - if (i == -1 && strlen(cA) == 0) { - free(cA); - return NULL; - } - char *cA2 = stString_copy(cA); - free(cA); - return cA2; -} - -char *stFile_pathJoin(const char *pathPrefix, const char *pathSuffix) { - return strlen(pathPrefix) == 0 || pathPrefix[strlen(pathPrefix) - 1] == '/' ? stString_print( - "%s%s", pathPrefix, pathSuffix) - : stString_print("%s/%s", pathPrefix, pathSuffix); -} - -bool stFile_exists(const char *fileName) { - struct stat info; - return !stat(fileName, &info); -} - -bool stFile_isDir(const char *fileName) { - if (!stFile_exists(fileName)) { - stThrowNew(ST_FILE_EXCEPTION, "File does not exist exist: %s\n", - fileName); - } - struct stat info; - if (stat(fileName, &info)) { - stThrowNew(ST_FILE_EXCEPTION, - "Failed to get information about the file: %s\n", fileName); - } - return S_ISDIR(info.st_mode); -} - -void stFile_mkdir(const char *dirName) { - if (stFile_exists(dirName)) { - stThrowNew(ST_FILE_EXCEPTION, - "Directory already appears to exist: %s\n", dirName); - } - int i = mkdir(dirName, S_IRWXU | S_IRWXG | S_IRWXO); - if (i) { - stThrowNew(ST_FILE_EXCEPTION, "Error code from mkdir function: %" PRIi64 "\n", - i); - } -} - -stList *stFile_getFileNamesInDirectory(const char *dir) { - if (!stFile_exists(dir)) { - stThrowNew(ST_FILE_EXCEPTION, "Directory does not exist exist: %s\n", - dir); - } - if (!stFile_isDir(dir)) { - stThrowNew(ST_FILE_EXCEPTION, - "Specified file is not a directory: %s\n", dir); - } - stList *files = stList_construct3(0, free); - DIR *dh = opendir(dir); - struct dirent *file;//a 'directory entity' AKA file - while ((file = readdir(dh)) != NULL) { - if (file->d_name[0] != '.') { - stList_append(files, stString_copy(file->d_name)); - } - } - closedir(dh); - return files; -} - -void stFile_rmrf(const char *fileName) { - if (!stFile_exists(fileName)) { - stThrowNew(ST_FILE_EXCEPTION, "File to remove does not exist: %s\n", - fileName); - } - st_system("rm -rf %s", fileName); -} diff --git a/C/impl/sonLibGlobalsInternal.h b/C/impl/sonLibGlobalsInternal.h deleted file mode 100644 index f8542a0..0000000 --- a/C/impl/sonLibGlobalsInternal.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibPrivate.h - * - * Created on: 21 May 2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_GLOBALS_INTERNAL_H_ -#define SONLIB_GLOBALS_INTERNAL_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "CuTest.h" -#include "sonLib.h" -#include "sonLibListPrivate.h" - - - -#endif /* SONLIBPRIVATE_H_ */ diff --git a/C/impl/sonLibHash.c b/C/impl/sonLibHash.c deleted file mode 100644 index 7465924..0000000 --- a/C/impl/sonLibHash.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibHash.c - * - * Created on: 4 Apr 2010 - * Author: benedictpaten - */ -#include "sonLibGlobalsInternal.h" -#include "hashTableC.h" -#include "hashTableC_itr.h" - -struct _stHash { - struct hashtable *hash; - bool destructKeys, destructValues; -}; - -uint64_t stHash_pointer(const void *k) { - // Size doesn't matter; just promote to 64 bits - uint64_t key = (uint64_t) k; - - // Use the hash from - // We can't just -ull these until C++11, if we're in C++ - key = (key ^ (key >> 30)) * UINT64_C(0xbf58476d1ce4e5b9); - key = (key ^ (key >> 27)) * UINT64_C(0x94d049bb133111eb); - return key ^ (key >> 31); -} - -static int stHash_equalKey(const void *key1, const void *key2) { - return key1 == key2; -} - -stHash *stHash_construct(void) { - return stHash_construct3(stHash_pointer, stHash_equalKey, NULL, NULL); -} - -stHash *stHash_construct2(void(*destructKeys)(void *), void(*destructValues)(void *)) { - return stHash_construct3(stHash_pointer, stHash_equalKey, destructKeys, destructValues); -} - -stHash *stHash_construct3(uint64_t(*hashKey)(const void *), int(*hashEqualsKey)(const void *, const void *), void(*destructKeys)(void *), void(*destructValues)(void *)) { - stHash *hash = st_malloc(sizeof(stHash)); - hash->hash = create_hashtable(0, hashKey, hashEqualsKey, destructKeys, destructValues); - hash->destructKeys = destructKeys != NULL; - hash->destructValues = destructValues != NULL; - return hash; -} - -void stHash_destruct(stHash *hash) { - hashtable_destroy(hash->hash, hash->destructValues, hash->destructKeys); - free(hash); -} - -void stHash_insert(stHash *hash, void *key, void *value) { - if (stHash_search(hash, key) != NULL) { //This will ensure we don't end up with duplicate keys.. - stHash_remove(hash, key); - } - hashtable_insert(hash->hash, key, value); -} - -void *stHash_search(stHash *hash, void *key) { - return hashtable_search(hash->hash, key); -} - -void *stHash_remove(stHash *hash, void *key) { - return hashtable_remove(hash->hash, key, 0); -} - -void *stHash_removeAndFreeKey(stHash *hash, void *key) { - return hashtable_remove(hash->hash, key, 1); -} - -int64_t stHash_size(stHash *hash) { - return hashtable_count(hash->hash); -} - -stHashIterator *stHash_getIterator(stHash *hash) { - return hashtable_iterator(hash->hash); -} - -void *stHash_getNext(stHashIterator *iterator) { - if (iterator->e != NULL) { - void *o = hashtable_iterator_key(iterator); - hashtable_iterator_advance(iterator); - return o; - } - return NULL; -} - -stHashIterator *stHash_copyIterator(stHashIterator *iterator) { - stHashIterator *iterator2 = st_malloc(sizeof(stHashIterator)); - iterator2->h = iterator->h; - iterator2->e = iterator->e; - iterator2->parent = iterator->parent; - iterator2->index = iterator->index; - return iterator2; -} - -void stHash_destructIterator(stHashIterator *iterator) { - free(iterator); -} - -stList *stHash_getKeys(stHash *hash) { - stList *list = stList_construct(); - stHashIterator *iterator = stHash_getIterator(hash); - void *item; - while ((item = stHash_getNext(iterator)) != NULL) { - stList_append(list, item); - } - stHash_destructIterator(iterator); - return list; -} - -stList *stHash_getValues(stHash *hash) { - stList *list = stList_construct(); - stHashIterator *iterator = stHash_getIterator(hash); - void *item; - while ((item = stHash_getNext(iterator)) != NULL) { - stList_append(list, stHash_search(hash, item)); - } - stHash_destructIterator(iterator); - return list; -} - -/* - * Useful hash keys/equals functions - */ - -uint64_t stHash_stringKey(const void *k) { - // djb2 - // This algorithm was first reported by Dan Bernstein - // many years ago in comp.lang.c - // - uint64_t hash = 0; //5381; - int c; - char *cA; - cA = (char *) k; - while ((c = *cA++) != '\0') { - hash = c + (hash << 6) + (hash << 16) - hash; - //hash = ((hash << 5) + hash) + c; // hash*33 + c - } - return hash; -} - -int stHash_stringEqualKey(const void *key1, const void *key2) { - return strcmp(key1, key2) == 0; -} - -stHash *stHash_invert(stHash *hash, uint64_t(*hashKey)(const void *), int(*equalsFn)(const void *, const void *), - void(*destructKeys)(void *), void(*destructValues)(void *)) { - /* - * Inverts the hash. - */ - stHash *invertedHash = stHash_construct3(hashKey, equalsFn, destructKeys, destructValues); - stHashIterator *hashIt = stHash_getIterator(hash); - void *key; - while ((key = stHash_getNext(hashIt)) != NULL) { - void *value = stHash_search(hash, key); - assert(value != NULL); - if (stHash_search(invertedHash, value) == NULL) { - stHash_insert(invertedHash, value, key); - } - } - stHash_destructIterator(hashIt); - return invertedHash; -} -// interface to underlying functions -uint64_t (*stHash_getHashFunction(stHash *hash))(const void *) { - return hash->hash->hashfn; -} -int (*stHash_getEqualityFunction(stHash *hash))(const void *, const void *) { - return hash->hash->eqfn; -} -void (*stHash_getKeyDestructorFunction(stHash *hash))(void *) { - return hash->hash->keyFree; -} -void (*stHash_getValueDestructorFunction(stHash *hash))(void *) { - return hash->hash->valueFree; -} - -static int unsigned_cmp(const unsigned *x, const unsigned *y) { - if (*x < *y) { - return -1; - } else if (*x == *y) { - return 0; - } else { - return 1; - } -} - -void stHash_printDiagnostics(stHash *hash) { - struct hashtable *h = hash->hash; - unsigned *bucketLoad = st_malloc(h->tablelength * sizeof(unsigned)); - unsigned *occupiedBucketLoad = st_malloc(h->entrycount * sizeof(unsigned)); - size_t occupiedBuckets = 0; - for (size_t i = 0; i < h->tablelength; i++) { - unsigned load = 0; - struct entry *e; - if ((e = h->table[i]) != NULL) { - while (e) { - load++; - e = e->next; - } - occupiedBucketLoad[occupiedBuckets++] = load; - } - bucketLoad[i] = load; - } - printf("Load: %" PRIi64 " / %" PRIi64 " (%lf%%)\n", h->entrycount, h->tablelength, ((double)h->entrycount)/h->tablelength * 100); - printf("# occupied buckets: %zu\n", occupiedBuckets); - qsort(bucketLoad, h->tablelength, sizeof(unsigned), (int (*)(const void *, const void *)) unsigned_cmp); - qsort(occupiedBucketLoad, occupiedBuckets, sizeof(unsigned), (int (*)(const void *, const void *)) unsigned_cmp); - printf("min load: %u, median load: %u, max load: %u\n", bucketLoad[0], bucketLoad[(h->tablelength - 1) / 2], - bucketLoad[h->tablelength - 1]); - printf("min occupied load: %u, avg occupied load: %lf, median occupied load: %u, max occupied load: %u\n", - occupiedBucketLoad[0], ((double)h->entrycount)/occupiedBuckets, - occupiedBucketLoad[(occupiedBuckets - 1) / 2], - occupiedBucketLoad[occupiedBuckets - 1]); - free(occupiedBucketLoad); - free(bucketLoad); -} diff --git a/C/impl/sonLibKVDatabase.c b/C/impl/sonLibKVDatabase.c deleted file mode 100644 index 1ee6648..0000000 --- a/C/impl/sonLibKVDatabase.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibKVDatabase.c - * - * Created on: 18-Aug-2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsInternal.h" -#include "sonLibKVDatabasePrivate.h" -#include "sonLibString.h" - -const char *ST_KV_DATABASE_EXCEPTION_ID = "ST_KV_DATABASE_EXCEPTION"; -const char *ST_KV_DATABASE_RETRY_TRANSACTION_EXCEPTION_ID = - "ST_KV_DATABASE_RETRY_TRANSACTION_EXCEPTION_ID"; - -static bool isRetryExcept(stExcept *except) { - return stExcept_idEq(except, ST_KV_DATABASE_RETRY_TRANSACTION_EXCEPTION_ID); -} - -stKVDatabase *stKVDatabase_construct(stKVDatabaseConf *conf, bool create) { - stKVDatabase *database = st_calloc(1, sizeof(struct stKVDatabase)); - database->conf = stKVDatabaseConf_constructClone(conf); - database->deleted = false; - - switch (stKVDatabaseConf_getType(conf)) { - case stKVDatabaseTypeTokyoCabinet: -#ifdef HAVE_TOKYO_CABINET - stKVDatabase_initialise_tokyoCabinet(database, conf, create); -#else - stThrowNew( - ST_KV_DATABASE_EXCEPTION_ID, - "requested Tokyo Cabinet database, however sonlib is not compiled with Tokyo Cabinet support"); -#endif - break; - case stKVDatabaseTypeKyotoTycoon: -#ifdef HAVE_KYOTO_TYCOON - stKVDatabase_initialise_kyotoTycoon(database, conf, create); -#else - stThrowNew( - ST_KV_DATABASE_EXCEPTION_ID, - "requested Kyoto Tycoon database, however sonlib is not compiled with Kyoto Tycoon support"); -#endif - break; - case stKVDatabaseTypeMySql: -#ifdef HAVE_MYSQL - stKVDatabase_initialise_MySql(database, conf, create); -#else - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "requested MySQL database, however sonlib is not compiled with MySql support"); -#endif - break; - default: - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "BUG: unrecognized database type"); - } - return database; -} - -void stKVDatabase_destruct(stKVDatabase *database) { - if (!database->deleted) { - stTry { - database->destruct(database); - }stCatch(ex) - { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_destruct failed"); - }stTryEnd; - } - stKVDatabaseConf_destruct(database->conf); - free(database); -} - -void stKVDatabase_deleteFromDisk(stKVDatabase *database) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to delete a database that has already been deleted"); - } - stTry { - database->deleteDatabase(database); - }stCatch(ex) - { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_deleteFromDisk failed"); - }stTryEnd; - database->deleted = true; -} - -bool stKVDatabase_containsRecord(stKVDatabase *database, int64_t key) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to check if a record is in a database that has been deleted"); - } - bool containsRecord = 0; - stTry { - containsRecord = database->containsRecord(database, key); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_containsRecord key %lld failed", - (long long) key); - } - }stTryEnd; - return containsRecord; -} - -void stKVDatabase_insertRecord(stKVDatabase *database, int64_t key, - const void *value, int64_t sizeOfRecord) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to insert a record into a database that has been deleted"); - } - if(value == NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to insert a null record into a database"); - } - stTry { - database->insertRecord(database, key, value, sizeOfRecord); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_insertRecord key %lld size %lld failed", - (long long) key, (long long) sizeOfRecord); - } - }stTryEnd; -} - -void stKVDatabase_insertInt64(stKVDatabase *database, int64_t key, int64_t value) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to insert a int64 record into a database that has been deleted"); - } - stTry { - database->insertInt64(database, key, value); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_insertRecord key %lld size %d failed", - (long long) key, sizeof(int64_t)); - } - }stTryEnd; -} - -void stKVDatabase_updateInt64(stKVDatabase *database, int64_t key, int64_t value) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to update a int64 record into a database that has been deleted"); - } - stTry { - database->updateInt64(database, key, value); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_updateInt64 key %lld size %d failed", - (long long) key, sizeof(int64_t)); - } - }stTryEnd; -} - -void stKVDatabase_updateRecord(stKVDatabase *database, int64_t key, - const void *value, int64_t sizeOfRecord) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to update a record in a database that has been deleted"); - } - if(value == NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to insert a null record into a database"); - } - stTry { - database->updateRecord(database, key, value, sizeOfRecord); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_updateRecord key %lld size %lld failed", - (long long) key, (long long) sizeOfRecord); - } - }stTryEnd; -} - -void stKVDatabase_setRecord(stKVDatabase *database, int64_t key, - const void *value, int64_t sizeOfRecord) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to get set a record from a database that has been deleted"); - } - if(value == NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to insert a null record into a database"); - } - stTry { - database->setRecord(database, key, value, sizeOfRecord); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_setRecord key %lld size %lld failed", - (long long) key, (long long) sizeOfRecord); - } - }stTryEnd; -} - -int64_t stKVDatabase_incrementInt64(stKVDatabase *database, int64_t key, - int64_t incrementAmount) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to increment a numerical record from a database that has been deleted"); - } - stTry { - return database->incrementInt64(database, key, incrementAmount); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_incrementRecord key: %lld increment size: %lld failed", - (long long) key, (long long) incrementAmount); - } - }stTryEnd; - assert(0); - return 0; -} - -static stKVDatabaseBulkRequest *stKVDatabaseBulkRequest_construct(int64_t key, - const void *value, int64_t sizeOfRecord, - enum stKVDatabaseBulkRequestType type) { - stKVDatabaseBulkRequest *buildRequest = st_malloc( - sizeof(stKVDatabaseBulkRequest)); - buildRequest->key = key; - if(value == NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to insert a null record into a database"); - } - buildRequest->value = memcpy(st_malloc(sizeOfRecord), value, sizeOfRecord); - buildRequest->size = sizeOfRecord; - buildRequest->type = type; - return buildRequest; -} - -stKVDatabaseBulkRequest *stKVDatabaseBulkRequest_constructInsertRequest( - int64_t key, const void *value, int64_t sizeOfRecord) { - return stKVDatabaseBulkRequest_construct(key, value, sizeOfRecord, INSERT); -} - -stKVDatabaseBulkRequest *stKVDatabaseBulkRequest_constructUpdateRequest( - int64_t key, const void *value, int64_t sizeOfRecord) { - return stKVDatabaseBulkRequest_construct(key, value, sizeOfRecord, UPDATE); -} - -stKVDatabaseBulkRequest *stKVDatabaseBulkRequest_constructSetRequest( - int64_t key, const void *value, int64_t sizeOfRecord) { - return stKVDatabaseBulkRequest_construct(key, value, sizeOfRecord, SET); -} - -void stKVDatabaseBulkRequest_destruct(stKVDatabaseBulkRequest *record) { - free(record->value); - free(record); -} - -void stKVDatabase_bulkSetRecords(stKVDatabase *database, stList *records) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to bulk set records from a database that has been deleted"); - } - stTry { - database->bulkSetRecords(database, records); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_bulkSetRecords with %" PRIi64 " records to update", - stList_length(records)); - } - }stTryEnd; -} - -void stKVDatabase_bulkRemoveRecords(stKVDatabase *database, stList *records) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to bulk remove records from a database that has been deleted"); - } - -#ifndef NDEBUG - /*This code to check the presence of records is very expensive*/ - for (int64_t i = 0; i < stList_length(records); i++) { - int64_t key = stIntTuple_get(stList_get(records, i), 0); - if (!stKVDatabase_containsRecord(database, key)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "The key is not in the database which we aim to remove: %lli", key); - } - } -#endif - stTry { - database->bulkRemoveRecords(database, records); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_bulkRemoveRecords with %" PRIi64 " records to update", - stList_length(records)); - } - }stTryEnd; -} - -int64_t stKVDatabase_getNumberOfRecords(stKVDatabase *database) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to get the number of records from a database that has been deleted"); - } - int64_t numRecs = 0; - stTry { - numRecs = database->numberOfRecords(database); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_getNumberOfRecords failed"); - } - }stTryEnd; - return numRecs; -} - -void *stKVDatabase_getRecord(stKVDatabase *database, int64_t key) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to get a record from a database that has already been deleted"); - } - void *data = NULL; - stTry { - data = database->getRecord(database, key); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_getRecord key %lld failed", - (long long) key); - } - }stTryEnd; - return data; -} - -int64_t stKVDatabase_getInt64(stKVDatabase *database, int64_t key) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to get a record from a database that has already been deleted"); - } - int64_t value = -1; - stTry { - value = database->getInt64(database, key); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_getInt64 key %lld failed", - (long long) key); - } - }stTryEnd; - return value; -} - -void *stKVDatabase_getRecord2(stKVDatabase *database, int64_t key, - int64_t *recordSize) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to get a record from a database that has already been deleted"); - } - void *data = NULL; - stTry { - data = database->getRecord2(database, key, recordSize); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_getRecord2 key %lld failed", - (long long) key); - } - }stTryEnd; - return data; -} - -void *stKVDatabase_getPartialRecord(stKVDatabase *database, int64_t key, - int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to get a record from a database that has already been deleted"); - } - if (zeroBasedByteOffset < 0 || sizeInBytes < 0 || zeroBasedByteOffset - + sizeInBytes > recordSize) { - stThrowNew( - ST_KV_DATABASE_EXCEPTION_ID, - "Partial record retrieval to out of bounds memory, requested start: %lld, requested size: %lld, entry size: %lld", - (long long) zeroBasedByteOffset, (long long) sizeInBytes, - (long long) recordSize); - } - void *data = NULL; - stTry { - data = database->getPartialRecord(database, key, - zeroBasedByteOffset, sizeInBytes, recordSize); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_getPartialRecord key %lld offset %lld size %lld failed", - (long long) key, (long long) zeroBasedByteOffset, - (long long) sizeInBytes); - } - }stTryEnd; - return data; -} - -stKVDatabaseBulkResult *stKVDatabaseBulkResult_construct(void* value, int64_t sizeOfRecord) -{ - /* convention is to not bother creating a result for NULL values */ - stKVDatabaseBulkResult* result = st_malloc(sizeof(stKVDatabaseBulkResult)); - result->value = value; - result->size = sizeOfRecord; - return result; -} - -void* stKVDatabaseBulkResult_getRecord(stKVDatabaseBulkResult* bulkResult, int64_t *sizeOfRecord) -{ - *sizeOfRecord = bulkResult->size; - return bulkResult->value; -} - -void stKVDatabaseBulkResult_destruct(stKVDatabaseBulkResult* bulkResult) -{ - free(bulkResult->value); - free(bulkResult); -} - -stList *stKVDatabase_bulkGetRecords(stKVDatabase *database, stList* keys) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to get records from a database that has already been deleted"); - } - assert(keys != NULL); - if(stList_length(keys) == 0) { - return stList_construct(); - } - stList *resultsList = NULL; - stTry { - resultsList = database->bulkGetRecords(database, keys); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_BulkGetRecords with %d records failed", - stList_length(keys)); - } - }stTryEnd; - return resultsList; -} - -stList *stKVDatabase_bulkGetRecordsRange(stKVDatabase *database, int64_t firstKey, int64_t numRecords){ - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to get records from a database that has already been deleted"); - } - assert(numRecords > 0); - stList *resultsList = NULL; - stTry { - resultsList = database->bulkGetRecordsRange(database, firstKey, numRecords); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_BulkGetRecords2 with %lld records failed", - (long long int)numRecords); - } - }stTryEnd; - return resultsList; -} - -void stKVDatabase_removeRecord(stKVDatabase *database, int64_t key) { - if (database->deleted) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Trying to remove a record from a database that has already been deleted"); - } - if (!stKVDatabase_containsRecord(database, key)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "The key is not in the database: %lli", key); - } - stTry { - database->removeRecord(database, key); - }stCatch(ex) - { - if (isRetryExcept(ex)) { - stThrow(ex); - } else { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, - "stKVDatabase_removeRecord key %lld failed", - (long long) key); - } - }stTryEnd; -} - -stKVDatabaseConf *stKVDatabase_getConf(stKVDatabase *database) { - return database->conf; -} diff --git a/C/impl/sonLibKVDatabaseConf.c b/C/impl/sonLibKVDatabaseConf.c deleted file mode 100644 index dbc59ad..0000000 --- a/C/impl/sonLibKVDatabaseConf.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibKVDatabaseConf.c - * - * Created on: 2010-08-23 - * Author: Mark Diekhans - */ - -#include "sonLibKVDatabaseConf.h" -#include "sonLibKVDatabase.h" -#include "sonLibExcept.h" -#include "sonLibTypes.h" -#include "sonLibString.h" -#include "stSafeC.h" -#include "sonLib.h" - -/* object storing the database configuration */ -struct stKVDatabaseConf { - stKVDatabaseType type; - char *databaseDir; - char *host; - unsigned port; - int timeout; - int64_t maxKTRecordSize; - int64_t maxKTBulkSetSize; - int64_t maxKTBulkSetNumRecords; - char *user; - char *password; - char *databaseName; - char *tableName; -}; - -stKVDatabaseConf *stKVDatabaseConf_constructTokyoCabinet(const char *databaseDir) { - stKVDatabaseConf *conf = stSafeCCalloc(sizeof(stKVDatabaseConf)); - conf->type = stKVDatabaseTypeTokyoCabinet; - conf->databaseDir = stString_copy(databaseDir); - return conf; -} - -stKVDatabaseConf *stKVDatabaseConf_constructKyotoTycoon(const char *host, unsigned port, int timeout, - int64_t maxRecordSize, int64_t maxBulkSetSize, - int64_t maxBulkSetNumRecords, - const char *databaseDir, const char* databaseName) { - stKVDatabaseConf *conf = stSafeCCalloc(sizeof(stKVDatabaseConf)); - conf->type = stKVDatabaseTypeKyotoTycoon; - conf->databaseDir = stString_copy(databaseDir); - conf->host = stString_copy(host); - conf->port = port; - conf->timeout = timeout; - conf->maxKTRecordSize = maxRecordSize; - conf->maxKTBulkSetSize = maxBulkSetSize; - conf->maxKTBulkSetNumRecords = maxBulkSetNumRecords; - conf->databaseName = stString_copy(databaseName); - return conf; -} - -static stKVDatabaseConf *constructSql(stKVDatabaseType type, const char *host, unsigned port, const char *user, const char *password, - const char *databaseName, const char *tableName) { - stKVDatabaseConf *conf = stSafeCCalloc(sizeof(stKVDatabaseConf)); - conf->type = type; - conf->host = stString_copy(host); - conf->port = port; - conf->user = stString_copy(user); - conf->password = stString_copy(password); - conf->databaseName = stString_copy(databaseName); - conf->tableName = stString_copy(tableName); - return conf; -} - -stKVDatabaseConf *stKVDatabaseConf_constructMySql(const char *host, unsigned port, const char *user, const char *password, - const char *databaseName, const char *tableName) { -#ifndef HAVE_MYSQL - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "requested MySQL database, however sonlib is not compiled with MySql support"); -#endif - return constructSql(stKVDatabaseTypeMySql, host, port, user, password, databaseName, tableName); -} - -char *getNextToken(char **tokenStream) { - char *token = stString_getNextWord(tokenStream); - if(token != NULL) { - char *cA = stString_replace(token, "\"", ""); - free(token); - token = stString_replace(cA, "'", ""); - free(cA); - } - return token; -} - -static void getExpectedToken(char **tokenStream, const char *expected) { - char *cA = getNextToken(tokenStream); - if (!stString_eq(cA, expected)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "BUG: expected the token: %s in database XML string, but I got: %s from the stream %s", - expected, cA, *tokenStream); - } - free(cA); -} - -static char *getKeyValue(char **tokenStream, const char *key) { - getExpectedToken(tokenStream, key); - return getNextToken(tokenStream); -} - -/* Parse XML string into a hash. This parses all attributes of all tags - * into values. st_kv_database_conf type is stored as conf_type, - * database tag is stores as db_tag. This does minimal error checking - * and is really lame. - */ -static stHash *hackParseXmlString(const char *xmlString) { - stHash *hash = stHash_construct3(stHash_stringKey, stHash_stringEqualKey, free, free); - char *toReplace[5] = { "", ">", "=" }; - char *cA = stString_replace(xmlString, toReplace[0], " "), *cA2; - for (int64_t i = 1; i < 5; i++) { - cA2 = stString_replace(cA, toReplace[i], " "); - free(cA); - cA = cA2; - } - getExpectedToken(&cA2, "st_kv_database_conf"); - stHash_insert(hash, stString_copy("conf_type"), getKeyValue(&cA2, "type")); - stHash_insert(hash, stString_copy("db_tag"), getNextToken(&cA2)); - - char *key; - while (((key = getNextToken(&cA2)) != NULL) && !stString_eq(key, "st_kv_database_conf")) { - char *value = getNextToken(&cA2); - if (value == NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "failed to to get value for key \"%s\"", key); - } - if (stHash_search(hash, key) != NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "got a duplicate entry in the database conf string \"%s\"", key); - } - stHash_insert(hash, key, value); - } - if(!stString_eq(key, "st_kv_database_conf")) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "got an unexpected final entry \"%s\"", key); - } - free(key); - free(cA); - return hash; -} - -static const char *getXmlValueRequired(stHash *hash, const char *key) { - const char *value = stHash_search(hash, (char*)key); - if (value == NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "did not find a \"%s\" value in the database XML string", key); - } - return value; -} - -static int getXmlPort(stHash *hash) { - const char *value = stHash_search(hash, "port"); - if (value == NULL) { - return 0; - } else { - return stSafeStrToUInt32(value); - } -} - -static int getXmlTimeout(stHash *hash) { - const char *value = stHash_search(hash, "timeout"); - if (value == NULL) { - // default to -1 -- meaning no timeout - return -1; - } else { - return stSafeStrToUInt32(value); - } -} - -/* Default to 50M. It used to be 175M but since noticing - * problems in bulk *get* within cactus secondary dbs we - * crank it way down. Unlike bulk set, in the get we don't - * know the total size of the requested records. To prevent - * big data transfers (which are problematic), we reduce max - * size of individual records and hope for the best - */ -static int64_t getXMLMaxKTRecordSize(stHash *hash) { - const char *value = stHash_search(hash, "max_record_size"); - if (value == NULL) { - return (int64_t) 10000000; - } else { - return stSafeStrToInt64(value); - } -} - -/* Default to 175M which seems to be about where the - * kyoto tycoon network error danger zone starts - */ -static int64_t getXMLMaxKTBulkSetSize(stHash *hash) { - const char *value = stHash_search(hash, "max_bulkset_size"); - if (value == NULL) { - return (int64_t) 183500800; - } else { - return stSafeStrToInt64(value); - } -} - -/* Default to tried-and-true value of 10000 - */ -static int64_t getXMLMaxKTBulkSetNumRecords(stHash *hash) { - const char *value = stHash_search(hash, "max_bulkset_num_records"); - if (value == NULL) { - return (int64_t) 10000; - } else { - return stSafeStrToInt64(value); - } -} - -static stKVDatabaseConf *constructFromString(const char *xmlString) { - stHash *hash = hackParseXmlString(xmlString); - stKVDatabaseConf *databaseConf = NULL; - const char *type = getXmlValueRequired(hash, "conf_type"); - const char *dbTag = getXmlValueRequired(hash, "db_tag"); - if (!stString_eq(type, dbTag)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Database XML tag \"%s\" did not match st_kv_database_conf type attribute", dbTag, type); - } - if (stString_eq(type, "tokyo_cabinet")) { - databaseConf = stKVDatabaseConf_constructTokyoCabinet(getXmlValueRequired(hash, "database_dir")); - } else if (stString_eq(type, "kyoto_tycoon")) { - databaseConf = stKVDatabaseConf_constructKyotoTycoon(getXmlValueRequired(hash, "host"), - getXmlPort(hash), - getXmlTimeout(hash), - getXMLMaxKTRecordSize(hash), - getXMLMaxKTBulkSetSize(hash), - getXMLMaxKTBulkSetNumRecords(hash), - getXmlValueRequired(hash, "database_dir"), - stHash_search(hash, "database_name")); - } else if (stString_eq(type, "mysql")) { - databaseConf = stKVDatabaseConf_constructMySql(getXmlValueRequired(hash, "host"), getXmlPort(hash), - getXmlValueRequired(hash, "user"), getXmlValueRequired(hash, "password"), - getXmlValueRequired(hash, "database_name"), getXmlValueRequired(hash, "table_name")); - } else { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "invalid database type \"%s\"", type); - } - stHash_destruct(hash); - return databaseConf; -} - -stKVDatabaseConf *stKVDatabaseConf_constructFromString(const char *xmlString) { - stKVDatabaseConf *conf = NULL; - stTry { - conf = constructFromString(xmlString); - } stCatch(ex) { - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, "Invalid database XML specification: %s", xmlString); - } stTryEnd; - return conf; -} - - -stKVDatabaseConf *stKVDatabaseConf_constructClone(stKVDatabaseConf *srcConf) { - stKVDatabaseConf *conf = stSafeCCalloc(sizeof(stKVDatabaseConf)); - conf->type = srcConf->type; - conf->databaseDir = stString_copy(srcConf->databaseDir); - conf->host = stString_copy(srcConf->host); - conf->port = srcConf->port; - conf->timeout = srcConf->timeout; - conf->maxKTRecordSize = srcConf->maxKTRecordSize; - conf->maxKTBulkSetSize = srcConf->maxKTBulkSetSize; - conf->maxKTBulkSetNumRecords = srcConf->maxKTBulkSetNumRecords; - conf->user = stString_copy(srcConf->user); - conf->password = stString_copy(srcConf->password); - conf->databaseName = stString_copy(srcConf->databaseName); - conf->tableName = stString_copy(srcConf->tableName); - return conf; -} - -void stKVDatabaseConf_destruct(stKVDatabaseConf *conf) { - if (conf != NULL) { - stSafeCFree(conf->databaseDir); - stSafeCFree(conf->host); - stSafeCFree(conf->user); - stSafeCFree(conf->password); - stSafeCFree(conf->databaseName); - stSafeCFree(conf->tableName); - stSafeCFree(conf); - } -} - -stKVDatabaseType stKVDatabaseConf_getType(stKVDatabaseConf *conf) { - return conf->type; -} - -const char *stKVDatabaseConf_getDir(stKVDatabaseConf *conf) { - return conf->databaseDir; -} - -const char *stKVDatabaseConf_getHost(stKVDatabaseConf *conf) { - return conf->host; -} - -unsigned stKVDatabaseConf_getPort(stKVDatabaseConf *conf) { - return conf->port; -} - -int stKVDatabaseConf_getTimeout(stKVDatabaseConf *conf) { - return conf->timeout; -} - -int64_t stKVDatabaseConf_getMaxKTRecordSize(stKVDatabaseConf *conf) { - return conf->maxKTRecordSize; -} - -int64_t stKVDatabaseConf_getMaxKTBulkSetSize(stKVDatabaseConf *conf) { - return conf->maxKTBulkSetSize; -} - -int64_t stKVDatabaseConf_getMaxKTBulkSetNumRecords(stKVDatabaseConf *conf) { - return conf->maxKTBulkSetNumRecords; -} - -const char *stKVDatabaseConf_getUser(stKVDatabaseConf *conf) { - return conf->user; -} - -const char *stKVDatabaseConf_getPassword(stKVDatabaseConf *conf) { - return conf->password; -} - -const char *stKVDatabaseConf_getDatabaseName(stKVDatabaseConf *conf) { - return conf->databaseName; -} - -const char *stKVDatabaseConf_getTableName(stKVDatabaseConf *conf) { - return conf->tableName; -} - diff --git a/C/impl/sonLibKVDatabasePrivate.h b/C/impl/sonLibKVDatabasePrivate.h deleted file mode 100644 index 075637c..0000000 --- a/C/impl/sonLibKVDatabasePrivate.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibKVDatabasePrivate.h - * - * Created on: 18 Aug 2010 - * Author: benedictpaten - */ - -#ifndef SONLIBKVDATABASEPRIVATE_H_ -#define SONLIBKVDATABASEPRIVATE_H_ - -struct stKVDatabase { - stKVDatabaseConf *conf; - void *dbImpl; - struct stKVDatabase* secondaryDB; - bool deleted; - void (*destruct)(stKVDatabase *); - void (*deleteDatabase)(stKVDatabase *); - bool (*containsRecord)(stKVDatabase *, int64_t); - void (*insertRecord)(stKVDatabase *, int64_t, const void *, int64_t); - void (*insertInt64)(stKVDatabase *, int64_t, int64_t); - void (*updateRecord)(stKVDatabase *, int64_t, const void *, int64_t); - void (*updateInt64)(stKVDatabase *, int64_t, int64_t); - void (*setRecord)(stKVDatabase *, int64_t, const void *, int64_t); - int64_t (*incrementInt64)(stKVDatabase *, int64_t, int64_t); - void (*bulkSetRecords)(stKVDatabase *, stList *); - void (*bulkRemoveRecords)(stKVDatabase *, stList *); - int64_t (*numberOfRecords)(stKVDatabase *); - void *(*getRecord)(stKVDatabase *, int64_t key); - int64_t (*getInt64)(stKVDatabase *, int64_t key); - void *(*getRecord2)(stKVDatabase *database, int64_t key, int64_t *recordSize); - void *(*getPartialRecord)(stKVDatabase *database, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize); - stList *(*bulkGetRecords)(stKVDatabase *database, stList* keys); - stList *(*bulkGetRecordsRange)(stKVDatabase *database, int64_t firstKey, int64_t numRecords); - void (*removeRecord)(stKVDatabase *, int64_t key); -}; - -enum stKVDatabaseBulkRequestType { - UPDATE, INSERT, SET -}; - -struct stKVDatabaseBulkRequest { - int64_t key; - void *value; - int64_t size; - enum stKVDatabaseBulkRequestType type; -}; - -struct stKVDatabaseBulkResult { - void *value; - int64_t size; -}; - -/* - * Function initialises the pointers of the stKVDatabase object with functions for tokyoCabinet. - */ -void stKVDatabase_initialise_tokyoCabinet(stKVDatabase *database, stKVDatabaseConf *conf, bool create); - -/* - * Function initialises the pointers of the stKVDatabase object with functions for MySql. - */ -void stKVDatabase_initialise_MySql(stKVDatabase *database, stKVDatabaseConf *conf, bool create); - -#ifdef __cplusplus -extern "C" { -#endif -void stKVDatabase_initialise_kyotoTycoon(stKVDatabase *database, stKVDatabaseConf *conf, bool create); -/* - * Function initialises the pointers of the stKVDatabase object with functions for Big Record File. - */ -void stKVDatabase_initialise_bigRecordFile(stKVDatabase *database, stKVDatabaseConf *conf, bool create); - -#ifdef __cplusplus -} -#endif - - -#endif /* SONLIBKVDATABASEPRIVATE_H_ */ diff --git a/C/impl/sonLibKVDatabase_BigRecordFile.c b/C/impl/sonLibKVDatabase_BigRecordFile.c deleted file mode 100644 index aae5934..0000000 --- a/C/impl/sonLibKVDatabase_BigRecordFile.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Glenn Hickey - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * Write records directly to binary files, in a one record per - * file scheme. Designed to be used in conjunction with Kyoto Tycoon - * as a work-around for "network errors" that invariably arise when - * trying to write large records (>200MB) to the database. - * - * Doesn't fully implement the sonLib database interface (and is not - * made public) but is consistent enough that it could be if needed... - */ - -#include -#include -#include -#include -#include -#include "sonLibGlobalsInternal.h" -#include "sonLibKVDatabasePrivate.h" -#include "sonLibSortedSet.h" -#include "stSafeC.h" -#include "sonLibTuples.h" - -/* - * tag used to construct files for storing big records. these all just - * get dumped in the database dir from the conf. note that this string - * is used, hackily, by cactus_progressive when deleting databases.. - */ -#define RECORD_FILE_TAG "BIG__RECORD__FILE__" - -/* - * Maximum number of records stored in the base directory. If there - * are too many files, it's probably time for a rethink. The value below - * is relatively high mostly just for unit testing. - */ -#define MAX_NUMBER_ENTRIES 2048 - -#define MAXIMUM_PATH_LENGTH 4096 -/* - * Get the full path of the file corresponding to the record - * with the given key. NEEDS TO BE FREED!! - */ -static char* createRecordPath(stKVDatabaseConf* conf, int64_t key) -{ - const char *basePath = stKVDatabaseConf_getDir(conf); - const char *name = stKVDatabaseConf_getDatabaseName(conf); - if (name == NULL) - name = "db"; - int64_t size = strlen(basePath) + strlen(name) + - strlen(RECORD_FILE_TAG) + 65; - char* recordPath = (char*)malloc(size * sizeof(char)); - sprintf(recordPath, "%s/%s.%s%lld", basePath, name, RECORD_FILE_TAG, - (long long int)key); - return recordPath; -} - -/* - * visit every record in the directory. currently implemented - * as just a flat directory where records are stored in files - * including the RECORD_FILE_TAG. - */ -static size_t visitRecords(const char* basePath, - void (*fileFn)(const char* recordPath, void* arg), void* argument) -{ - DIR *dp; - struct dirent *ep; - char filePathBuffer[MAXIMUM_PATH_LENGTH]; - dp = opendir(basePath); - int64_t numRecords = 0; - if (dp != NULL) - { - while ((ep = readdir(dp)) != NULL) - { - if (strstr(ep->d_name, RECORD_FILE_TAG) != NULL) - { - sprintf(filePathBuffer, "%s/%s", basePath, ep->d_name); - if (fileFn != NULL) - { - fileFn(filePathBuffer, argument); - } - ++numRecords; - } - } - (void)closedir(dp); - } - return numRecords; -} - -/* - * add a path to a sorted set - */ -static void add_to_sortedSet(const char* recordPath, void* arg) -{ - stSortedSet* sortedSet = (stSortedSet*)arg; - const char* fileName = strstr(recordPath, RECORD_FILE_TAG); - assert (fileName != NULL); - const char* keyString = fileName + strlen(RECORD_FILE_TAG); - assert (keyString != NULL); - int64_t key = atol(keyString); - stSortedSet_insert(sortedSet, stIntTuple_construct1( key)); -} - -/* get around complicated casting - */ -static void remove_with_arg(const char* path, void* arg) -{ - remove(path); -} - -/* - * build a sorted set of records in the given directory - */ -static stSortedSet* constructDB(stKVDatabaseConf *conf, bool create) -{ - const char *basePath = stKVDatabaseConf_getDir(conf); - mkdir(basePath, S_IRWXU); - stSortedSet* sortedSet = stSortedSet_construct3( - (int (*)(const void *, const void *))stIntTuple_cmpFn, - (void (*)(void *))stIntTuple_destruct); - if (create == true) - { - visitRecords(basePath, remove_with_arg, NULL); - } - else - { - visitRecords(basePath, add_to_sortedSet, sortedSet); - } - return sortedSet; -} - -/* - * database in memory is just a sorted set, so we destroy that. - */ -static void destructDB(stKVDatabase *database) -{ - stSortedSet* sortedSet = (stSortedSet*)database->dbImpl; - if (sortedSet != NULL) - { - stSortedSet_destruct(sortedSet); - } - database->dbImpl = NULL; -} - -/* delete every file beginning with RECORD_FILE_TAG - * in the database directory - */ -static void deleteDB(stKVDatabase *database) -{ - /* destruct called to be consistent with other dbs */ - destructDB(database); - stKVDatabaseConf* conf = stKVDatabase_getConf(database); - const char *basePath = stKVDatabaseConf_getDir(conf); - visitRecords(basePath, remove_with_arg, NULL); -} - -/* check if a record already exists */ -static bool containsRecord(stKVDatabase *database, int64_t key) -{ - stSortedSet* sortedSet = (stSortedSet*)database->dbImpl; - stIntTuple* tuple = stIntTuple_construct1( key); - void* found = stSortedSet_search(sortedSet, tuple); - stIntTuple_destruct(tuple); - return found != NULL; -} - -/* write the record as a file in the directory, and add the key - * to the in-memory sorted set. - */ -static void insertRecord(stKVDatabase *database, int64_t key, const void *value, - int64_t sizeOfRecord) -{ - stSortedSet* sortedSet = (stSortedSet*)database->dbImpl; - if (stSortedSet_size(sortedSet) >= MAX_NUMBER_ENTRIES) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Database capacity reached: %lld", (int64_t)MAX_NUMBER_ENTRIES); - } - char* recordPath = createRecordPath(stKVDatabase_getConf(database), key); - FILE* recHandle = fopen(recordPath, "wb"); - if (recHandle == NULL) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Open file: %s", recordPath); - } - size_t retVal = fwrite(value, sizeOfRecord, 1, recHandle); - if (retVal != 1) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Write file: %s", recordPath); - } - stSortedSet_insert(sortedSet, stIntTuple_construct1( key)); - fclose(recHandle); - free(recordPath); -} - - -static void updateRecord(stKVDatabase *database, int64_t key, const void *value, - int64_t sizeOfRecord) -{ - insertRecord(database, key, value, sizeOfRecord); -} - -static void setRecord(stKVDatabase *database, int64_t key, const void *value, - int64_t sizeOfRecord) -{ - insertRecord(database, key, value, sizeOfRecord); -} - -static int64_t numberOfRecords(stKVDatabase *database) -{ - stSortedSet* sortedSet = (stSortedSet*)database->dbImpl; - return (int64_t)stSortedSet_size(sortedSet); -} - -/* - * NEEDS TO BE FREED - */ -static void* getRecord2(stKVDatabase *database, int64_t key, int64_t* recordSize) -{ - if (containsRecord(database, key) == false) - { - return NULL; - } - char* recordPath = createRecordPath(stKVDatabase_getConf(database), key); - FILE* recHandle = fopen(recordPath, "rb"); - if (recHandle == NULL) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Read file: %s", recordPath); - } - fseek(recHandle, 0, SEEK_END); - long fileSize = ftell(recHandle); - rewind(recHandle); - void* buffer = stSafeCMalloc(fileSize); - size_t retVal = fread(buffer, fileSize, 1, recHandle); - if (retVal != 1) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Read file: %s", recordPath); - } - fclose(recHandle); - free(recordPath); - *recordSize = fileSize; - return buffer; -} - -/* - * NEEDS TO BE FREED - */ -static void* getRecord(stKVDatabase *database, int64_t key) -{ - int64_t i; - return getRecord2(database, key, &i); -} - -/* get part of a string record */ -static void *getPartialRecord(stKVDatabase *database, int64_t key, - int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize) -{ - assert (zeroBasedByteOffset + sizeInBytes <= recordSize); - if (containsRecord(database, key) == false || sizeInBytes == 0) - { - return NULL; - } - char* recordPath = createRecordPath(stKVDatabase_getConf(database), key); - FILE* recHandle = fopen(recordPath, "rb"); - if (recHandle == NULL) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Read file: %s", recordPath); - } - fseek(recHandle, (long)zeroBasedByteOffset, 0); - void* buffer = stSafeCMalloc(sizeInBytes); - size_t retVal = fread(buffer, sizeInBytes, 1, recHandle); - if (retVal != 1) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Read file: %s", recordPath); - } - fclose(recHandle); - free(recordPath); - return buffer; -} - -static void removeRecord(stKVDatabase *database, int64_t key) -{ - if (containsRecord(database, key) == false) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Removing key not found: %lld", key); - } - stSortedSet* sortedSet = (stSortedSet*)database->dbImpl; - stIntTuple* tuple = stIntTuple_construct1( key); - stSortedSet_remove(sortedSet, tuple); - stIntTuple_destruct(tuple); - char* recordPath = createRecordPath(stKVDatabase_getConf(database), key); - int retVal = remove(recordPath); - if (retVal != 0) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, - "Removing file returned error %d: %lld ", retVal, key); - } - free(recordPath); -} - -void stKVDatabase_initialise_bigRecordFile(stKVDatabase *database, - stKVDatabaseConf *conf, bool create) -{ - database->dbImpl = constructDB(stKVDatabase_getConf(database), create); - database->secondaryDB = NULL; - database->destruct = destructDB; - database->deleteDatabase = deleteDB; - database->containsRecord = containsRecord; - database->insertRecord = insertRecord; - database->insertInt64 = NULL; - database->updateRecord = updateRecord; - database->updateInt64 = NULL; - database->setRecord = setRecord; - database->incrementInt64 = NULL; - database->bulkSetRecords = NULL; - database->bulkRemoveRecords = NULL; - database->numberOfRecords = numberOfRecords; - database->getRecord = getRecord; - database->getInt64 = NULL; - database->getRecord2 = getRecord2; - database->getPartialRecord = getPartialRecord; - database->bulkGetRecords = NULL; - database->bulkGetRecordsRange = NULL; - database->removeRecord = removeRecord; -} - - diff --git a/C/impl/sonLibKVDatabase_KyotoTycoon.cpp b/C/impl/sonLibKVDatabase_KyotoTycoon.cpp deleted file mode 100644 index 383abbb..0000000 --- a/C/impl/sonLibKVDatabase_KyotoTycoon.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibKVDatabase_KyotoTycoon.cpp - * - * Created on: 5-1-11 - * Author: epaull - * - * Note: all the KT methods seem to have a C and a CPP version (in terms of the arguments) , - * and for this implementation we're using the plain C versions as much as we can. - * - * Update October 24, 2011 by Glenn Hickey: - * Added "secondaryDB" which points to instance of BigRecordFile type database - * as a fallback for big records. Now records of a certain size (from conf) - * don't get added to the kyoto tycoon but go into this new database instead. - * The whole thing should be transparent to the client, and hopefully prevent - * the dreaded network errors in the kyoto tycoon API. - * Note that all operations that can change a record's size must check to make - * sure that it does not get duplicated across the two db's! - * - * Feb 16, 2012: Multiple database on one server deprecated to implement - * the binary bulk functions (which require an index). This functionality - * could be reintroduced if we keep a name / index mapping externally (or find - * a way to pry it out of the api) - */ - -//Database functions -#ifdef HAVE_KYOTO_TYCOON -#include -#include -#include -#include -#include "sonLibGlobalsInternal.h" -#include "sonLibKVDatabasePrivate.h" - -using namespace std; -using namespace kyototycoon; - - -// the default expiration time: negative means indefinite, I believe -int64_t XT = kc::INT64MAX; - -/* - * construct in the Kyoto Tycoon case means connect to the remote DB -*/ -static RemoteDB *constructDB(stKVDatabaseConf *conf, bool create) { - - // we actually do need a local DB dir for Kyoto Tycoon to store the sequences file - const char *dbDir = stKVDatabaseConf_getDir(conf); - mkdir(dbDir, S_IRWXU); // just let open of database generate error (FIXME: would be better to make this report errors) - - - const char *dbRemote_Host = stKVDatabaseConf_getHost(conf); - unsigned dbRemote_Port = stKVDatabaseConf_getPort(conf); - int timeout = stKVDatabaseConf_getTimeout(conf); - - // create the database object - RemoteDB *rdb = new RemoteDB(); - - // tcrdb open sets the host and port for the rdb object - if (!rdb->open(dbRemote_Host, dbRemote_Port, timeout)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Opening connection to host: %s with error: %s", dbRemote_Host, rdb->error().name()); - } - - return rdb; -} - -static stKVDatabase* constructBigRecordDB(stKVDatabaseConf *conf, bool create) { - if (stKVDatabaseConf_getMaxKTRecordSize(conf) != kc::INT64MAX) { - // warning: bypassing stKVDatabase_construct() - stKVDatabase *database = (stKVDatabase *)st_calloc(1, sizeof(struct stKVDatabase)); - database->conf = stKVDatabaseConf_constructClone(conf); - database->deleted = false; - stKVDatabase_initialise_bigRecordFile(database, conf, create); - return database; - } - return NULL; -} - -/* closes the remote DB connection and deletes the rdb object, but does not destroy the -remote database */ -static void destructDB(stKVDatabase *database) { - RemoteDB *rdb = (RemoteDB*)database->dbImpl; - if (rdb != NULL) { - - // close the connection: first try a graceful close, then a forced close - if (!rdb->close(true)) { - if (!rdb->close(false)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Closing database error: %s",rdb->error().name()); - } - } - // delete the local in-memory object - delete rdb; - database->dbImpl = NULL; - } - if (database->secondaryDB != NULL) { - stKVDatabase_destruct(database->secondaryDB); - } -} - -/* WARNING: removes all records from the remote database */ -static void deleteDB(stKVDatabase *database) { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - if (rdb != NULL) { - rdb->clear(); - } - if (database->secondaryDB != NULL) { - database->secondaryDB->deleteDatabase(database->secondaryDB); - } - destructDB(database); - // this removes all records from the remove database object -} - - -/* check if a record already exists in the kt database*/ -static bool recordInTycoon(stKVDatabase *database, int64_t key) { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - size_t sp; - char *cA; - if ((cA = rdb->get((char *)&key, (size_t)sizeof(key), &sp, NULL)) == NULL) { - return false; - } else { - delete cA; - return true; - } -} - -/* check if a record already exists in the kt database*/ -static bool recordOnDisk(stKVDatabase *database, int64_t key) -{ - if (database->secondaryDB != NULL) - { - return database->secondaryDB->containsRecord(database->secondaryDB, key); - } - return false; -} - -/* remove a record from the disk cache if it exists. must be called before - * adding a record with this key to the tycoon. - */ -static void removeRecordFromTycoonIfPresent(stKVDatabase *database, int64_t key) -{ - if (recordInTycoon(database, key) == true) { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - if (!rdb->remove((char *)&key, (size_t)sizeof(int64_t))) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Removing key/value to database error: %s", rdb->error().name()); - } - } -} - -/* remove a record from the tycoon if it exists. must be called before - * adding a record with this key to the disk cache. - */ -static void removeRecordFromDiskIfPresent(stKVDatabase *database, int64_t key) -{ - if (recordOnDisk(database, key) == true) { - database->secondaryDB->removeRecord(database->secondaryDB, key); - } -} - - -static bool containsRecord(stKVDatabase *database, int64_t key) { - bool found = recordInTycoon(database, key); - if (found == false && database->secondaryDB != NULL) - { - found = recordOnDisk(database, key); - } - return found; -} - -static void insertRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) { - stKVDatabaseConf* conf = stKVDatabase_getConf(database); - int64_t maxRecordSize = stKVDatabaseConf_getMaxKTRecordSize(conf); - if (sizeOfRecord > maxRecordSize) - { - assert(database->secondaryDB != NULL); - removeRecordFromTycoonIfPresent(database, key); - database->secondaryDB->insertRecord(database->secondaryDB, key, value, sizeOfRecord); - } - else - { - removeRecordFromDiskIfPresent(database, key); - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - - size_t sizeOfKey = sizeof(int64_t); - // add method: If the key already exists the record will not be modified and it'll return false - if (!rdb->add((char *)&key, sizeOfKey, (const char *)value, sizeOfRecord)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Inserting key/value to database error: %s", rdb->error().name()); - } - } -} - -static void insertInt64(stKVDatabase *database, int64_t key, int64_t value) { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - - // Normalize a 64-bit number in the native order into the network byte order. - // little endian (our x86 linux machine) to big Endian.... - int64_t KCSafeIV = kyotocabinet::hton64(value); - - if (!rdb->add((char *)&key, sizeof(int64_t), (const char *)&KCSafeIV, sizeof(int64_t))) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Inserting int64 key/value to database error: %s", rdb->error().name()); - } -} - -static void updateInt64(stKVDatabase *database, int64_t key, int64_t value) { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - - // Normalize a 64-bit number in the native order into the network byte order. - // little endian (our x86 linux machine) to big Endian.... - uint64_t KCSafeIV = kyotocabinet::hton64(value); - - if (!rdb->replace((char *)&key, sizeof(int64_t), (const char *)&KCSafeIV, sizeof(int64_t))) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Updating int64 key/value to database error: %s", rdb->error().name()); - } -} - -static void updateRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) { - stKVDatabaseConf* conf = stKVDatabase_getConf(database); - int64_t maxRecordSize = stKVDatabaseConf_getMaxKTRecordSize(conf); - if (sizeOfRecord > maxRecordSize) - { - assert(database->secondaryDB != NULL); - removeRecordFromTycoonIfPresent(database, key); - database->secondaryDB->updateRecord(database->secondaryDB, key, value, sizeOfRecord); - } - else - { - removeRecordFromDiskIfPresent(database, key); - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - // replace method: If the key doesn't already exist it won't be created, and we'll get an error - if (!rdb->replace((char *)&key, (size_t)sizeof(int64_t), (const char *)value, sizeOfRecord)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Updating key/value to database error: %s", rdb->error().name()); - } - } -} - -static void setRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) { - stKVDatabaseConf* conf = stKVDatabase_getConf(database); - int64_t maxRecordSize = stKVDatabaseConf_getMaxKTRecordSize(conf); - if (sizeOfRecord > maxRecordSize) - { - assert(database->secondaryDB != NULL); - removeRecordFromTycoonIfPresent(database, key); - database->secondaryDB->setRecord(database->secondaryDB, key, value, sizeOfRecord); - } - else - { - removeRecordFromDiskIfPresent(database, key); - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - if (!rdb->set((char *)&key, (size_t)sizeof(int64_t), (const char *)value, sizeOfRecord)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "kyoto tycoon setting key/value failed: %s", rdb->error().name()); - } - } -} - -/* increment a record by the specified numerical value: atomic operation */ -/* return the new record value */ -static int64_t incrementInt64(stKVDatabase *database, int64_t key, int64_t incrementAmount) { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - int64_t returnValue = kyotocabinet::INT64MIN; - - size_t sizeOfKey = sizeof(int64_t); - - if ( (returnValue = rdb->increment((char *)&key, sizeOfKey, incrementAmount, kyotocabinet::INT64MIN, XT)) == kyotocabinet::INT64MIN ) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "kyoto tycoon incremement record failed: %s", rdb->error().name()); - } - - return returnValue; -} - -// sets a bulk list of records atomically -static void bulkSetRecords(stKVDatabase *database, stList *records) { - stKVDatabaseConf* conf = stKVDatabase_getConf(database); - int64_t maxRecordSize = stKVDatabaseConf_getMaxKTRecordSize(conf); - int64_t maxBulkSetSize = stKVDatabaseConf_getMaxKTBulkSetSize(conf); - int64_t maxBulkSetNumRecords = stKVDatabaseConf_getMaxKTBulkSetNumRecords(conf); - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - vector recs; - recs.reserve(stList_length(records)); - RemoteDB::BulkRecord templateRec; - templateRec.dbidx = 0; - templateRec.xt = XT; - int64_t runningSize = 0; - - // copy the records from our C data structure to the CPP map needed for the Tycoon API - for(int32_t i=0; isize > maxBulkSetSize || - (int64_t)recs.size() >= maxBulkSetNumRecords) && recs.empty() == false) { - int64_t retVal = rdb->set_bulk_binary(recs); - if (retVal < 1) { - assert(rdb->error().name() != NULL); - fprintf(stderr, "Throwing an exception with the string %s\n", rdb->error().name()); - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "kyoto tycoon set bulk record failed: %s", rdb->error().name()); - } - recs.clear(); - runningSize = 0; - } - // record too big for kt, we put in the secondary - if (request->size > maxRecordSize) { - assert(database->secondaryDB != NULL); - removeRecordFromTycoonIfPresent(database, request->key); - database->secondaryDB->setRecord(database->secondaryDB, request->key, request->value, request->size); - } - else - { - removeRecordFromDiskIfPresent(database, request->key); - templateRec.key = string((const char *)&(request->key), sizeof(int64_t)); - templateRec.value = string((const char *)request->value, request->size); - recs.push_back(templateRec); - runningSize += request->size; - } - } - - // test for empty list - if (recs.empty() == false) { - // set values, atomic = true - int64_t retVal = rdb->set_bulk_binary(recs); - if (retVal < 1) { - assert(rdb->error().name() != NULL); - fprintf(stderr, "Throwing an exception with the string %s\n", rdb->error().name()); - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "kyoto tycoon set bulk record failed: %s", rdb->error().name()); - } - } - //printf("size of insert: %d\n", retVal); -} - -// remove a bulk list atomically -static void bulkRemoveRecords(stKVDatabase *database, stList *records) { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - vector keys; - - for(int32_t i=0; isecondaryDB->removeRecord(database->secondaryDB, key); - } - else { - keys.push_back(string((const char *)&key, sizeof(int64_t))); - } - } - - // test for empty list - if (keys.empty()) { - return; - } - - if (rdb->remove_bulk(keys, true) < 1) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "kyoto tycoon bulk remove record failed: %s", rdb->error().name()); - } -} - -static int64_t numberOfRecords(stKVDatabase *database) { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - int64_t count = rdb->count(); - if (database->secondaryDB != NULL) { - count += database->secondaryDB->numberOfRecords(database->secondaryDB); - } - return count; -} - -static void *getRecord2(stKVDatabase *database, int64_t key, int64_t *recordSize) { - char* record = NULL; - if (recordOnDisk(database, key) == true) - { - record = (char*)database->secondaryDB->getRecord2(database->secondaryDB, key, recordSize); - } - else if (recordInTycoon(database, key) == true) - { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - //Return value must be freed. - size_t i; - char* newRecord = rdb->get((char *)&key, (size_t)sizeof(int64_t), &i, NULL); - *recordSize = (int64_t)i; - record = (char*)memcpy(st_malloc(*recordSize), newRecord, *recordSize); - delete newRecord; - } - - return record; -} - -/* get a single non-string record */ -static void *getRecord(stKVDatabase *database, int64_t key) { - int64_t i; - return getRecord2(database, key, &i); -} - -/* get a single non-string record */ -static int64_t getInt64(stKVDatabase *database, int64_t key) { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - - size_t sp; - char *newRecord = rdb->get((char *)&key, sizeof(int64_t), &sp, NULL); - char* record = (char*)memcpy(st_malloc( sizeof(int64_t)), newRecord, sizeof(int64_t)); - delete newRecord; - - // convert from KC native big-endian back to little-endian Intel... - return kyotocabinet::ntoh64(*((int64_t*)record)); -} - -/* get part of a string record */ -static void *getPartialRecord(stKVDatabase *database, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize) { - stKVDatabaseConf* conf = stKVDatabase_getConf(database); - int64_t maxRecordSize = stKVDatabaseConf_getMaxKTRecordSize(conf); - if (recordSize > maxRecordSize) - { - assert (database->secondaryDB != NULL); - if (recordOnDisk(database, key) == false) - { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "The record does not exist: %lld for partial retrieval", (long long)key); - } - return database->secondaryDB->getPartialRecord(database->secondaryDB, key, zeroBasedByteOffset, sizeInBytes, recordSize); - } - else - { - int64_t recordSize2; - char *record = (char *)getRecord2(database, key, &recordSize2); - if(recordSize2 != recordSize) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "The given record size is incorrect: %lld, should be %lld", (long long)recordSize, recordSize2); - } - if(record == NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "The record does not exist: %lld for partial retrieval", (long long)key); - } - if(zeroBasedByteOffset < 0 || sizeInBytes < 0 || zeroBasedByteOffset + sizeInBytes > recordSize) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Partial record retrieval to out of bounds memory, record size: %lld, requested start: %lld, requested size: %lld", (long long)recordSize, (long long)zeroBasedByteOffset, (long long)sizeInBytes); - } - void *partialRecord = memcpy(st_malloc(sizeInBytes), record + zeroBasedByteOffset, sizeInBytes); - free(record); - return partialRecord; - } -} - -/* do a bulk get based on a list of keys. */ -static stList *bulkGetRecords(stKVDatabase *database, stList* keys) -{ - stKVDatabaseConf* conf = stKVDatabase_getConf(database); - int64_t maxBulkSetNumRecords = stKVDatabaseConf_getMaxKTBulkSetNumRecords(conf); - int32_t n = stList_length(keys); - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - RemoteDB::BulkRecord templateRec; - templateRec.dbidx = 0; - templateRec.xt = XT; - vector recs; - recs.reserve(std::min(maxBulkSetNumRecords, (int64_t)n)); - stList* results = stList_construct3(n, (void(*)(void *))stKVDatabaseBulkResult_destruct); - int32_t prevI = 0; - for (int32_t i = 0; i < n; ++i) - { - int64_t key = *(int64_t*)stList_get(keys, i); - if (recordOnDisk(database, key) == true) - { - int64_t recordSize; - void *record = database->secondaryDB->getRecord2(database->secondaryDB, key, &recordSize); - stKVDatabaseBulkResult* result = stKVDatabaseBulkResult_construct(record, recordSize); - stList_set(results, i, result); - } - else - { - templateRec.key = string((char*)stList_get(keys, i), (size_t)sizeof(int64_t)); - recs.push_back(templateRec); - } - - if (recs.size() >= (uint64_t)maxBulkSetNumRecords || (i == n - 1 && !recs.empty())) - { - int64_t retVal = rdb->get_bulk_binary(&recs); - if (retVal < 0) - { - assert(rdb->error().name() != NULL); - fprintf(stderr, "Throwing a KT exception with the string %s\n", rdb->error().name()); - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "kyoto tycoon get bulk record failed: %s", rdb->error().name()); - } - int32_t recIdx = 0; - for (int32_t j = prevI; j <= i; ++j) - { - if (stList_get(results, j) == NULL) - { - RemoteDB::BulkRecord& curRecord = recs.at(recIdx++); - int64_t recordSize = curRecord.value.length() * sizeof(char); - void* record = st_malloc(recordSize); - memcpy(record, curRecord.value.data(), recordSize); - stKVDatabaseBulkResult* result = stKVDatabaseBulkResult_construct(record, recordSize); - stList_set(results, j, result); - } - } - recs.clear(); - prevI = i + 1; - } - } - return results; -} - -static stList *bulkGetRecordsRange(stKVDatabase *database, int64_t firstKey, int64_t numRecords) { - vector keysVec; - keysVec.reserve(numRecords); - stList* results = stList_construct3(numRecords, (void(*)(void *))stKVDatabaseBulkResult_destruct); - for (int64_t i = 0; i < numRecords; ++i) { - int64_t key = firstKey + i; - if (recordOnDisk(database, key) == true) - { - int64_t recordSize; - void *record = database->secondaryDB->getRecord2(database->secondaryDB, key, &recordSize); - stKVDatabaseBulkResult* result = stKVDatabaseBulkResult_construct(record, recordSize); - stList_set(results, (int32_t)i, result); - } - else - { - keysVec.push_back(string((char*)&key, (size_t)sizeof(int64_t))); - } - } - if (keysVec.empty() == false) - { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - map recs; - int64_t retVal = rdb->get_bulk(keysVec, &recs); - if (retVal < 0) - { - assert(rdb->error().name() != NULL); - fprintf(stderr, "Throwing a KT exception with the string %s\n", rdb->error().name()); - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "kyoto tycoon get bulk record failed: %s", rdb->error().name()); - } - for (int64_t i = 0; i < numRecords; ++i) - { - if (stList_get(results, (int32_t)i) == NULL) - { - int64_t key = firstKey + i; - string keyString = string((char*)&key, (size_t)sizeof(int64_t)); - map::iterator mapIt = recs.find(keyString); - void* record = NULL; - int64_t recordSize = 0; - if (mapIt != recs.end()) - { - recordSize = mapIt->second.length() * sizeof(char); - record = st_malloc(recordSize); - memcpy(record, mapIt->second.data(), recordSize); - } - stKVDatabaseBulkResult* result = stKVDatabaseBulkResult_construct(record, recordSize); - stList_set(results, (int32_t)i, result); - } - } - } - return results; -} - -static void removeRecord(stKVDatabase *database, int64_t key) { - if (recordOnDisk(database, key) == true) { - database->secondaryDB->removeRecord(database->secondaryDB, key); - } - else - { - RemoteDB *rdb = (RemoteDB *)database->dbImpl; - if (!rdb->remove((char *)&key, (size_t)sizeof(int64_t))) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Removing key/value to database error: %s", rdb->error().name()); - } - } -} - - -void stKVDatabase_initialise_kyotoTycoon(stKVDatabase *database, stKVDatabaseConf *conf, bool create) { - database->dbImpl = constructDB(stKVDatabase_getConf(database), create); - database->secondaryDB = constructBigRecordDB(stKVDatabase_getConf(database), create); - database->destruct = destructDB; - database->deleteDatabase = deleteDB; - database->containsRecord = containsRecord; - database->insertRecord = insertRecord; - database->insertInt64 = insertInt64; - database->updateRecord = updateRecord; - database->updateInt64 = updateInt64; - database->setRecord = setRecord; - database->incrementInt64 = incrementInt64; - database->bulkSetRecords = bulkSetRecords; - database->bulkRemoveRecords = bulkRemoveRecords; - database->numberOfRecords = numberOfRecords; - database->getRecord = getRecord; - database->getInt64 = getInt64; - database->getRecord2 = getRecord2; - database->getPartialRecord = getPartialRecord; - database->bulkGetRecords = bulkGetRecords; - database->bulkGetRecordsRange = bulkGetRecordsRange; - database->removeRecord = removeRecord; -} - -#endif diff --git a/C/impl/sonLibKVDatabase_MySql.c b/C/impl/sonLibKVDatabase_MySql.c deleted file mode 100644 index edeb852..0000000 --- a/C/impl/sonLibKVDatabase_MySql.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibKVDatabase_MySql.c - * - * Created on: 2010-08-21 - * Author: Mark Diekhans - */ - -//Database functions - -#include "sonLibGlobalsInternal.h" -#include "sonLibKVDatabasePrivate.h" -#include "stSafeC.h" - -#ifdef HAVE_MYSQL - -#include -#include - -/* mysql client data object, stored in stKVDatabase object */ -typedef struct { - MYSQL *conn; - char *table; -} MySqlDb; - -static MYSQL_RES *queryStart(MySqlDb *dbImpl, const char *query, ...) -#if defined(__GNUC__) -__attribute__((format(printf, 2, 3))) -#endif -; - -static void sqlExec(MySqlDb *dbImpl, char *query, ...) -#if defined(__GNUC__) -__attribute__((format(printf, 2, 3))) -#endif -; - -/* is this a mysql error were the transaction should be retried */ -static bool isMysqlRetryError(int mysqlErrNo) { - return (mysqlErrNo == ER_LOCK_DEADLOCK) || (mysqlErrNo == ER_LOCK_WAIT_TIMEOUT); -} - -/* create an exception for the current MySQL error */ -static stExcept *createMySqlExceptv(MySqlDb *dbImpl, const char *msg, va_list args) { - char *fmtMsg = stSafeCDynFmtv(msg, args); - const char *exId = isMysqlRetryError(mysql_errno(dbImpl->conn)) ? ST_KV_DATABASE_RETRY_TRANSACTION_EXCEPTION_ID : ST_KV_DATABASE_EXCEPTION_ID; - stExcept *except = stExcept_new(exId, "%s: %s (%d)", fmtMsg, mysql_error(dbImpl->conn), mysql_errno(dbImpl->conn)); - stSafeCFree(fmtMsg); - return except; -} - -/* create an exception for the current MySQL error */ -static stExcept *createMySqlExcept(MySqlDb *dbImpl, const char *msg, ...) { - va_list args; - va_start(args, msg); - stExcept *except = createMySqlExceptv(dbImpl, msg, args); - va_end(args); - return except; -} - -/* generate an exception for the current MySQL error */ -static void throwMySqlExcept(MySqlDb *dbImpl, const char *msg, ...) { - va_list args; - va_start(args, msg); - stExcept *except = createMySqlExceptv(dbImpl, msg, args); - va_end(args); - stThrow(except); -} - -/* start an SQL query, formatting arguments into the query */ -static MYSQL_RES *queryStartv(MySqlDb *dbImpl, const char *query, va_list args) { - char *sql = stSafeCDynFmtv(query, args); - if (mysql_real_query(dbImpl->conn, sql, strlen(sql)) != 0) { - stExcept *ex = createMySqlExcept(dbImpl, "query failed \"%0.60s\"", sql); - stSafeCFree(sql); - stThrow(ex); - } - MYSQL_RES *rs = mysql_use_result(dbImpl->conn); - if ((rs == NULL) && (mysql_errno(dbImpl->conn) != 0)) { - stExcept *ex = createMySqlExcept(dbImpl, "query failed \"%0.60s\"", sql); - stSafeCFree(sql); - stThrow(ex); - } - stSafeCFree(sql); - return rs; -} - -/* start an SQL query, formatting arguments into the query */ -static MYSQL_RES *queryStart(MySqlDb *dbImpl, const char *query, ...) { - va_list args; - va_start(args, query); - MYSQL_RES *rs = queryStartv(dbImpl, query, args); - va_end(args); - return rs; -} - -static char **queryNext(MySqlDb *dbImpl, MYSQL_RES *rs) { - if (rs == NULL) { - return NULL; - } - char **row = mysql_fetch_row(rs); - if (mysql_errno(dbImpl->conn) != 0) { - throwMySqlExcept(dbImpl, "query fetch failed"); - } - return row; -} - -static char **queryNextRequired(MySqlDb *dbImpl, MYSQL_RES *rs) { - char **row = queryNext(dbImpl, rs); - if (row == NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "query did not return required result"); - } - return row; -} - -static size_t queryLength(MySqlDb *dbImpl, MYSQL_RES *rs) { - unsigned long *lens = mysql_fetch_lengths(rs); - if (mysql_errno(dbImpl->conn) != 0) { - throwMySqlExcept(dbImpl, "mysql_fetch_lengths failed"); - } - return lens[0]; -} - -// collect warnings into an array -static int getWarnings(MySqlDb *dbImpl, int maxToReport, char **warnings) { - int numReturned = 0; - MYSQL_RES *rs = queryStart(dbImpl, "show warnings limit %d", maxToReport); - char **row; - while ((row = queryNext(dbImpl, rs)) != NULL) { - if (numReturned < maxToReport) { - warnings[numReturned++] = stSafeCDynFmt("%s: %s (%s)", row[0], row[2], row[1]); - } - } - mysql_free_result(rs); - return numReturned; -} - -// collect warnings, concat into a string -static char *getWarningsStr(MySqlDb *dbImpl) { - static const int maxToReport = 5; - char *warnings[maxToReport]; - int numReturned = getWarnings(dbImpl, maxToReport, warnings); - char *warningsStr = stString_join("\n", (const char**)warnings, numReturned); - for (int i = 0; i < numReturned; i++) { - stSafeCFree(warnings[i]); - } - return warningsStr; -} - -// and throw an expection -static void throwWarnings(MySqlDb *dbImpl) { - int numWarnings = mysql_warning_count(dbImpl->conn); - char *warningsStr = getWarningsStr(dbImpl); - stExcept *ex = stExcept_new(ST_KV_DATABASE_EXCEPTION_ID, "MySQL request had %d warning(s), possible data lose: %s", numWarnings, warningsStr); - stSafeCFree(warningsStr); - stThrow(ex); -} - -static void queryEnd(MySqlDb *dbImpl, MYSQL_RES *rs) { - if (rs != NULL) { - mysql_free_result(rs); - } - if (mysql_warning_count(dbImpl->conn) != 0) { - throwWarnings(dbImpl); - } -} - -/* SQL escape a byte string, result must be freed */ -static char *sqlEscape(MySqlDb *dbImpl, const void *data, size_t size) { - char *escBuf = stSafeCMalloc((2*size)+1); - mysql_real_escape_string(dbImpl->conn, escBuf, data, size); - return escBuf; -} - -/* immediate execution of a statement that doesn't return results, formatting - * arguments into query */ -static void sqlExec(MySqlDb *dbImpl, char *query, ...) { - va_list args; - va_start(args, query); - MYSQL_RES *rs = queryStartv(dbImpl, query, args); - va_end(args); - if (queryNext(dbImpl, rs) != NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "SQL command should not have returned a result: \"%s\"", query); - } - queryEnd(dbImpl, rs); -} - -/* disconnect and free MySqlDb object */ -static void disconnect(MySqlDb *dbImpl) { - if (dbImpl->conn != NULL) { - mysql_close(dbImpl->conn); - } - stSafeCFree(dbImpl->table); - stSafeCFree(dbImpl); -} - -/* connect to a database server */ -static MySqlDb *connect(stKVDatabaseConf *conf) { - MySqlDb *dbImpl = stSafeCCalloc(sizeof(MySqlDb)); - if ((dbImpl->conn = mysql_init(NULL)) == NULL) { - disconnect(dbImpl); - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "mysql_init failed"); - } - if (mysql_real_connect(dbImpl->conn, stKVDatabaseConf_getHost(conf), stKVDatabaseConf_getUser(conf), stKVDatabaseConf_getPassword(conf), stKVDatabaseConf_getDatabaseName(conf), stKVDatabaseConf_getPort(conf), NULL, 0) == NULL) { - stExcept *ex = createMySqlExcept(dbImpl, "failed to connect to MySql database: %s on %s as user %s", - stKVDatabaseConf_getDatabaseName(conf), stKVDatabaseConf_getHost(conf), stKVDatabaseConf_getUser(conf)); - disconnect(dbImpl); - stThrow(ex); - } - dbImpl->table = stString_copy(stKVDatabaseConf_getTableName(conf)); - - // disable report of notes, so only warnings and errors come back - sqlExec(dbImpl, "set sql_notes=0"); - - // set max sizes of an sql statment to 1G. This must also be specified - // for the server by adding "max_allowed_packet = 1G" to the [mysqld] - // section of my.cnf - sqlExec(dbImpl, "set global max_allowed_packet=1073741824"); - - // set the idle timeout to a week - int waitTimeout = 7 * 24 * 60 * 60; // 1 week - sqlExec(dbImpl, "set wait_timeout=%d", waitTimeout); - - // set the read timeout to an hour - int readTimeout = 60 * 60; // 1 hour - sqlExec(dbImpl, "set net_read_timeout=%d", readTimeout); - - // NOTE: commit will not return an error, this does row-level locking on - // the select done before the update - sqlExec(dbImpl, "set autocommit = 0;"); - sqlExec(dbImpl, "set session transaction isolation level serializable;"); - return dbImpl; -} - -/* create the keyword/value table */ -static void createKVTable(MySqlDb *dbImpl) { - sqlExec(dbImpl, "drop table if exists %s", dbImpl->table); - sqlExec(dbImpl, "create table %s (id bigint primary key, data longblob) engine=INNODB;", dbImpl->table); -} - -static void destructDB(stKVDatabase *database) { - MySqlDb *dbImpl = database->dbImpl; - disconnect(dbImpl); - database->dbImpl = NULL; -} - -static void deleteDB(stKVDatabase *database) { - MySqlDb *dbImpl = database->dbImpl; - sqlExec(dbImpl, "drop table %s", dbImpl->table); - destructDB(database); -} - -static void updateInt64(stKVDatabase *database, int64_t key, int64_t value) { - MySqlDb *dbImpl = database->dbImpl; - char *buf = sqlEscape(dbImpl, &value, sizeof(int64_t)); - sqlExec(dbImpl, "update %s set data=\"%s\" where id=%lld", dbImpl->table, buf, (long long)key); -} - -static void insertInt64(stKVDatabase *database, int64_t key, int64_t value) { - MySqlDb *dbImpl = database->dbImpl; - char *buf = sqlEscape(dbImpl, &value, sizeof(int64_t)); - sqlExec(dbImpl, "insert into %s (id, data) values (%lld, \"%s\")", dbImpl->table, (long long)key, buf); -} - -static void insertRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) { - MySqlDb *dbImpl = database->dbImpl; - char *buf = sqlEscape(dbImpl, value, sizeOfRecord); - sqlExec(dbImpl, "insert into %s (id, data) values (%lld, \"%s\")", dbImpl->table, (long long)key, buf); - stSafeCFree(buf); -} - -static void updateRecord(stKVDatabase *database, int64_t key, - const void *value, int64_t sizeOfRecord) { - MySqlDb *dbImpl = database->dbImpl; - char *buf = sqlEscape(dbImpl, value, sizeOfRecord); - sqlExec(dbImpl, "update %s set data=\"%s\" where id=%lld", dbImpl->table, buf, (long long)key); - stSafeCFree(buf); -} - -static int64_t numberOfRecords(stKVDatabase *database) { - MySqlDb *dbImpl = database->dbImpl; - MYSQL_RES *rs = queryStart(dbImpl, "select count(*) from %s", dbImpl->table); - char **row = queryNextRequired(dbImpl, rs); - int64_t numRecords = stSafeStrToInt64(row[0]); - queryEnd(dbImpl, rs); - return numRecords; -} - -static void *getRecord2(stKVDatabase *database, int64_t key, int64_t *sizeOfRecord) { - MySqlDb *dbImpl = database->dbImpl; - MYSQL_RES *rs = queryStart(dbImpl, "select data from %s where id=%lld", dbImpl->table, (long long)key); - char **row = queryNext(dbImpl, rs); - void *data = NULL; - int64_t readLen = 0; - if (row != NULL) { - readLen = queryLength(dbImpl, rs); - data = stSafeCCopyMem(row[0], readLen); - } - queryEnd(dbImpl, rs); - if (sizeOfRecord != NULL) { - *sizeOfRecord = readLen; - } - return data; -} - -static int64_t getInt64(stKVDatabase *database, int64_t key) { - void *record = getRecord2(database, key, NULL); - return *((int64_t*)record); -} - -static void *getRecord(stKVDatabase *database, int64_t key) { - return getRecord2(database, key, NULL); -} - -static bool containsRecord(stKVDatabase *database, int64_t key) { - MySqlDb *dbImpl = database->dbImpl; - MYSQL_RES *rs = queryStart(dbImpl, "select id from %s where id=%lld", dbImpl->table, (long long)key); - char **row = queryNext(dbImpl, rs); - bool found = (row != NULL); - queryEnd(dbImpl, rs); - return found; -} - -static void *getPartialRecord(stKVDatabase *database, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize) { - MySqlDb *dbImpl = database->dbImpl; - MYSQL_RES *rs = queryStart(dbImpl, "select substring(data, %lld, %lld) from %s where id=%lld", (long long)zeroBasedByteOffset+1, (long long)sizeInBytes, dbImpl->table, (long long)key); - char **row = queryNext(dbImpl, rs); - void *data = NULL; - int64_t readLen = 0; - if (row != NULL) { - readLen = queryLength(dbImpl, rs); - data = stSafeCCopyMem(row[0], readLen); - } - queryEnd(dbImpl, rs); - if (readLen != sizeInBytes) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "partial read of key %lld, expected %lld bytes got %lld bytes", (long long)key, (long long)sizeInBytes, (long long)readLen); - } - return data; -} - -static void startTransaction(stKVDatabase *database) { - MySqlDb *dbImpl = database->dbImpl; - sqlExec(dbImpl, "start transaction with consistent snapshot;"); -} - -static void commitTransaction(stKVDatabase *database) { - MySqlDb *dbImpl = database->dbImpl; - sqlExec(dbImpl, "commit;"); -} - -static void abortTransaction(stKVDatabase *database) { - MySqlDb *dbImpl = database->dbImpl; - sqlExec(dbImpl, "rollback;"); -} - -static void removeRecord(stKVDatabase *database, int64_t key) { - MySqlDb *dbImpl = database->dbImpl; - sqlExec(dbImpl, "delete from %s where id=%lld", dbImpl->table, (long long)key); - my_ulonglong numRows = mysql_affected_rows(dbImpl->conn); - if (numRows == 0) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "remove of non-existent key %lld", (long long)key); - } -} - -static int64_t incrementInt64(stKVDatabase *database, int64_t key, int64_t incrementAmount) { - startTransaction(database); - int64_t returnValue = INT64_MIN; - stTry { - int64_t recordSize; - int64_t *record = getRecord2(database, key, &recordSize); - assert(recordSize >= sizeof(int64_t)); - record[0] += incrementAmount; - returnValue = record[0]; - updateRecord(database, key, record, recordSize); - free(record); - commitTransaction(database); - }stCatch(ex) { - abortTransaction(database); - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "MySQL increment record failed"); - }stTryEnd; - return returnValue; -} - -//TODO: make one command -static void bulkRemoveRecords(stKVDatabase *database, stList *records) { - startTransaction(database); - stTry { - for(int64_t i=0; itype) { - case UPDATE: - updateRecord(database, request->key, request->value, request->size); - break; - case INSERT: - insertRecord(database, request->key, request->value, request->size); - break; - case SET: - setRecord(database, request->key, request->value, request->size); - break; - } - } - commitTransaction(database); - }stCatch(ex) { - abortTransaction(database); - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "MySQL bulk set records failed"); - }stTryEnd; -} - -//initialisation function -void stKVDatabase_initialise_MySql(stKVDatabase *database, stKVDatabaseConf *conf, bool create) { - database->dbImpl = connect(conf); - database->destruct = destructDB; - database->deleteDatabase = deleteDB; - database->containsRecord = containsRecord; - database->insertRecord = insertRecord; - database->insertInt64 = insertInt64; - database->updateRecord = updateRecord; - database->updateInt64 = updateInt64; - database->setRecord = setRecord; - database->incrementInt64 = incrementInt64; - database->bulkSetRecords = bulkSetRecords; - database->bulkRemoveRecords = bulkRemoveRecords; - database->numberOfRecords = numberOfRecords; - database->getRecord = getRecord; - database->getInt64 = getInt64; - database->getRecord2 = getRecord2; - database->getPartialRecord = getPartialRecord; - database->bulkGetRecords = bulkGetRecords; - database->bulkGetRecordsRange = bulkGetRecordsRange; - database->removeRecord = removeRecord; - if (create) { - createKVTable(database->dbImpl); - } -} - -#endif diff --git a/C/impl/sonLibKVDatabase_TokyoCabinet.c b/C/impl/sonLibKVDatabase_TokyoCabinet.c deleted file mode 100644 index 2ed418b..0000000 --- a/C/impl/sonLibKVDatabase_TokyoCabinet.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibKVDatabase_TokyoCabinet.c - * - * Created on: 18-Aug-2010 - * Author: benedictpaten - */ - -//Database functions - -#include "sonLibGlobalsInternal.h" -#include "sonLibKVDatabasePrivate.h" - -#ifdef HAVE_TOKYO_CABINET -#include -#include - -static int keyCmp(const char *vA1, int size1, const char *vA2, - int size2, void *a) { - assert(size1 == sizeof(int64_t)); - assert(size2 == sizeof(int64_t)); - assert(a == NULL); - int64_t i = *(int64_t *) vA1; - int64_t j = *(int64_t *) vA2; - return i - j > 0 ? 1 : (i < j ? -1 : 0); -} - -static TCBDB *constructDB(stKVDatabaseConf *conf, bool create) { - const char *dbDir = stKVDatabaseConf_getDir(conf); - mkdir(dbDir, S_IRWXU); // just let open of database generate error (FIXME: would be better to make this report errors) - char *databaseName = stString_print("%s/%s", dbDir, "data"); - TCBDB *dbImpl = tcbdbnew(); - tcbdbsetcmpfunc(dbImpl, keyCmp, NULL); - unsigned opts = BDBOWRITER | (create ? BDBOCREAT|BDBOTRUNC : 0); - if (!tcbdbopen(dbImpl, databaseName, opts)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Opening database: %s with error: %s", databaseName, tcbdberrmsg(tcbdbecode(dbImpl))); - } - free(databaseName); - return dbImpl; -} - -static void destructDB(stKVDatabase *database) { - TCBDB *dbImpl = database->dbImpl; - if (dbImpl != NULL) { - if (!tcbdbclose(dbImpl)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Closing database error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } - tcbdbdel(dbImpl); - database->dbImpl = NULL; - } -} - -static void deleteDB(stKVDatabase *database) { - destructDB(database); - const char *dbDir = stKVDatabaseConf_getDir(stKVDatabase_getConf(database)); - int64_t i = st_system("rm -rf %s", dbDir); - if (i != 0) { - st_errAbort("Tried to delete the temporary cactus disk: %s with exit code %d", dbDir, i); - } -} - -/* check if a record already exists */ -static bool recordExists(TCBDB *dbImpl, int64_t key) { - return tcbdbvnum(dbImpl, &key, sizeof(int64_t)) > 0; -} - -static bool containsRecord(stKVDatabase *database, int64_t key) { - return recordExists(database->dbImpl, key); -} - -static void insertRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) { - TCBDB *dbImpl = database->dbImpl; - if (recordExists(dbImpl, key)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Attempt to insert a key in the database that already exists: %lld", (long long)key); - } - if (!tcbdbput(dbImpl, &key, sizeof(int64_t), value, sizeOfRecord)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Inserting key/value to database error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } -} - -static void insertInt64(stKVDatabase *database, int64_t key, int64_t value) { - TCBDB *dbImpl = database->dbImpl; - - if (recordExists(dbImpl, key)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Attempt to insert a key in the database that already exists: %lld", (long long)key); - } - if (!tcbdbput(dbImpl, &key, sizeof(int64_t), (const void *)&value, sizeof(int64_t))) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Inserting key/value to database error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } -} - -static void updateRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) { - TCBDB *dbImpl = database->dbImpl; - if (!recordExists(dbImpl, key)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Attempt to update a key in the database that doesn't exists: %lld", (long long)key); - } - if (!tcbdbput(dbImpl, &key, sizeof(int64_t), value, sizeOfRecord)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Updating key/value to database error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } -} - -static void updateInt64(stKVDatabase *database, int64_t key, int64_t value) { - TCBDB *dbImpl = database->dbImpl; - if (!recordExists(dbImpl, key)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Attempt to update a key in the database that doesn't exists: %lld", (long long)key); - } - if (!tcbdbput(dbImpl, &key, sizeof(int64_t), (const void *)&value, sizeof(int64_t))) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Updating key/value to database error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } -} - -static void setRecord(stKVDatabase *database, int64_t key, - const void *value, int64_t sizeOfRecord) { - TCBDB *dbImpl = database->dbImpl; - if (!tcbdbput(dbImpl, &key, sizeof(int64_t), value, sizeOfRecord)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Set key/value to database error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } -} - -static void startTransaction(stKVDatabase *database) { - TCBDB *dbImpl = database->dbImpl; - if (!tcbdbtranbegin(dbImpl)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Tried to start a transaction but got error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } -} - -static void commitTransaction(stKVDatabase *database) { - TCBDB *dbImpl = database->dbImpl; - //Commit the transaction.. - if (!tcbdbtrancommit(dbImpl)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Tried to commit a transaction but got error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } -} - -static void abortTransaction(stKVDatabase *database) { - TCBDB *dbImpl = database->dbImpl; - if (!tcbdbtranabort(dbImpl)) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Tried to abort a transaction but got error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } -} - -static void bulkSetRecords(stKVDatabase *database, stList *records) { - startTransaction(database); - stTry { - for(int64_t i=0; itype) { - case UPDATE: - updateRecord(database, request->key, request->value, request->size); - break; - case INSERT: - insertRecord(database, request->key, request->value, request->size); - break; - case SET: - setRecord(database, request->key, request->value, request->size); - break; - } - } - commitTransaction(database); - }stCatch(ex) { - abortTransaction(database); - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "tokyo cabinet bulk set records failed"); - }stTryEnd; -} - -static int64_t numberOfRecords(stKVDatabase *database) { - TCBDB *dbImpl = database->dbImpl; - return tcbdbrnum(dbImpl); -} - -static void *getRecord2(stKVDatabase *database, int64_t key, int64_t *recordSize) { - TCBDB *dbImpl = database->dbImpl; - //Return value must be freed. - int32_t i; - void *record = tcbdbget(dbImpl, &key, sizeof(int64_t), &i); - *recordSize = i; - return record; -} - -static int64_t getInt64(stKVDatabase *database, int64_t key) { - TCBDB *dbImpl = database->dbImpl; - //Return value must be freed. - int32_t i; - void *record = tcbdbget(dbImpl, &key, sizeof(int64_t), &i); - - if (record == NULL) { - return -1; - } else { - return *((int64_t*)record); - } -} - -static void *getRecord(stKVDatabase *database, int64_t key) { - int64_t i; - return getRecord2(database, key, &i); -} - -static int64_t incrementInt64(stKVDatabase *database, int64_t key, int64_t incrementAmount) { - startTransaction(database); - int64_t returnValue = INT64_MIN; - stTry { - int64_t recordSize; - int64_t *record = getRecord2(database, key, &recordSize); - assert(recordSize >= sizeof(int64_t)); - record[0] += incrementAmount; - returnValue = record[0]; - updateRecord(database, key, record, recordSize); - free(record); - commitTransaction(database); - }stCatch(ex) { - abortTransaction(database); - stThrowNewCause( - ex, - ST_KV_DATABASE_EXCEPTION_ID, - "tokyo cabinet increment record failed"); - }stTryEnd; - return returnValue; -} - -static void *getPartialRecord(stKVDatabase *database, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize) { - int64_t recordSize2; - char *record = getRecord2(database, key, &recordSize2); - if(recordSize2 != recordSize) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "The given record size is incorrect: %lld, should be %lld", (long long)recordSize, recordSize2); - } - if(record == NULL) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "The record does not exist: %lld for partial retrieval", (long long)key); - } - if(zeroBasedByteOffset < 0 || sizeInBytes < 0 || zeroBasedByteOffset + sizeInBytes > recordSize) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Partial record retrieval to out of bounds memory, record size: %lld, requested start: %lld, requested size: %lld", (long long)recordSize, (long long)zeroBasedByteOffset, (long long)sizeInBytes); - } - void *partialRecord = memcpy(st_malloc(sizeInBytes), record + zeroBasedByteOffset, sizeInBytes); - free(record); - return partialRecord; -} - -static stList *bulkGetRecords(stKVDatabase *database, stList* keys) { - int64_t n = stList_length(keys); - stList* results = stList_construct3(n, (void(*)(void *))stKVDatabaseBulkResult_destruct); - //startTransaction(database); - stTry { - for (int64_t i = 0; i < n; ++i) - { - int64_t key = *((int64_t*)stList_get(keys, i)); - int64_t recordSize; - void* record = getRecord2(database, key, &recordSize); - stKVDatabaseBulkResult* result = stKVDatabaseBulkResult_construct(record, recordSize); - stList_set(results, i, result); - } - //commitTransaction(database); - }stCatch(ex) { - //abortTransaction(database); - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, "tokyo cabinet bulk get records failed"); - }stTryEnd; - - return results; -} - -static stList *bulkGetRecordsRange(stKVDatabase *database, int64_t firstKey, int64_t numRecords) { - stList* results = stList_construct3(numRecords, (void(*)(void *))stKVDatabaseBulkResult_destruct); - //startTransaction(database); - stTry { - for (int64_t i = 0; i < numRecords; ++i) - { - int64_t key = firstKey + i; - int64_t recordSize; - void* record = getRecord2(database, key, &recordSize); - stKVDatabaseBulkResult* result = stKVDatabaseBulkResult_construct(record, recordSize); - stList_set(results, i, result); - } - //commitTransaction(database); - }stCatch(ex) { - //abortTransaction(database); - stThrowNewCause(ex, ST_KV_DATABASE_EXCEPTION_ID, "tokyo cabinet bulk get records failed"); - }stTryEnd; - - return results; -} - -static void removeRecord(stKVDatabase *database, int64_t key) { - TCBDB *dbImpl = database->dbImpl; - if (!tcbdbout(dbImpl, &key, sizeof(int64_t))) { - stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Removing key/value to database error: %s", tcbdberrmsg(tcbdbecode(dbImpl))); - } -} - -static void bulkRemoveRecords(stKVDatabase *database, stList *records) { - startTransaction(database); - stTry { - for(int64_t i=0; idbImpl = constructDB(stKVDatabase_getConf(database), create); - database->destruct = destructDB; - database->deleteDatabase = deleteDB; - database->containsRecord = containsRecord; - database->insertRecord = insertRecord; - database->insertInt64 = insertInt64; - database->updateRecord = updateRecord; - database->updateInt64 = updateInt64; - database->setRecord = setRecord; - database->incrementInt64 = incrementInt64; - database->bulkSetRecords = bulkSetRecords; - database->bulkRemoveRecords = bulkRemoveRecords; - database->numberOfRecords = numberOfRecords; - database->getRecord = getRecord; - database->getInt64 = getInt64; - database->getRecord2 = getRecord2; - database->getPartialRecord = getPartialRecord; - database->bulkGetRecords = bulkGetRecords; - database->bulkGetRecordsRange = bulkGetRecordsRange; - database->removeRecord = removeRecord; -} - -#endif diff --git a/C/impl/sonLibList.c b/C/impl/sonLibList.c deleted file mode 100644 index a896d19..0000000 --- a/C/impl/sonLibList.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibList.c - * - * Created on: 24 May 2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsInternal.h" - -#define MINIMUM_ARRAY_EXPAND_SIZE 5 //The minimum amount to expand the array backing a list by when it is rescaled. - -/* - * The actual datastructures backing the list - */ - -/* - * The functions.. - */ - -stList *stList_construct(void) { - return stList_construct3(0, NULL); -} - -stList *stList_construct2(int64_t size) { - return stList_construct3(size, NULL); -} - -stList *stList_construct3(int64_t length, void (*destructElement)(void *)) { - assert(length >= 0); - stList *list = st_malloc(sizeof(stList)); - list->length = length; - list->maxLength = length; - list->list = st_calloc(length, sizeof(void *)); - list->destructElement = destructElement; - return list; -} - -/* free elements in list */ -static void destructElements(stList *list) { - for(int64_t i=0; idestructElement(stList_get(list, i)); - } - } -} - -void stList_destruct(stList *list) { - if (list != NULL) { - if (list->destructElement != NULL) { - destructElements(list); - } - if(list->list != NULL) { - free(list->list); - } - free(list); - } -} - -int64_t stList_length(stList *list) { - if (list == NULL) { - return 0; - } else { - return list->length; - } -} - -void *stList_get(stList *list, int64_t index) { - assert(index >= 0); - assert(index < stList_length(list)); - return list->list[index]; -} - -void stList_set(stList *list, int64_t index, void *item) { - assert(index >= 0); - assert(index < stList_length(list)); - list->list[index] = item; -} - -static void *st_list_appendP(void *current, int64_t *currentSize, int64_t newSize, int64_t base) { - assert(*currentSize <= newSize); - void *new; - new = memcpy(st_malloc(((int64_t)base)*newSize), current, ((int64_t)base)*(*currentSize)); - if(current != NULL) { - free(current); - } - *currentSize = newSize; - return new; -} - -void stList_append(stList *list, void *item) { - if(stList_length(list) >= list->maxLength) { - list->list = st_list_appendP(list->list, &list->maxLength, list->maxLength*2 + MINIMUM_ARRAY_EXPAND_SIZE, sizeof(void *)); - } - list->list[list->length++] = item; -} - -void stList_appendAll(stList *stListToAddTo, stList *stListToAdd) { - int64_t i; - assert(stListToAdd != stListToAddTo); - for(i=0; i 0); - return stList_get(list, stList_length(list)-1); -} - -void *stList_pop(stList *list) { - // FIXME: this would more natural to use if it return NULL when empty - return stList_remove(list, stList_length(list)-1); -} - -void *stList_remove(stList *list, int64_t index) { - assert(index >= 0); - assert(index < stList_length(list)); - void *o = stList_get(list, index); - int64_t i; - for(i=index+1; ilength--; - return o; -} - -void stList_removeItem(stList *list, void *item) { - int64_t i; - for(i=0; ilist = list; - it->index = 0; - return it; -} - -void stList_destructIterator(stListIterator *iterator) { - free(iterator); -} - -void *stList_getNext(stListIterator *iterator) { - if ((iterator->list == NULL) || (iterator->index >= stList_length(iterator->list))) { - return NULL; - } else { - return stList_get(iterator->list, iterator->index++); - } -} - -void *stList_getPrevious(stListIterator *iterator) { - if ((iterator->list == NULL) || (iterator->index == 0)) { - return NULL; - } else { - return stList_get(iterator->list, --iterator->index); - } -} - -stListIterator *stList_copyIterator(stListIterator *iterator) { - stListIterator *it = stList_getIterator(iterator->list); - it->index = iterator->index; - return it; -} - -static int (*st_list_sort_cmpFn)(const void *a, const void *b); -static int st_list_sortP(const void *a, const void *b) { - return st_list_sort_cmpFn(*((char **)a), *((char **)b)); -} - -void stList_sort(stList *list, int cmpFn(const void *a, const void *b)) { - st_list_sort_cmpFn = cmpFn; - qsort(list->list, stList_length(list), sizeof(void *), st_list_sortP); -} - -static int (*st_list_sort2_cmpFn)(const void *a, const void *b, const void *extraArg); -static const void *st_list_sort2_extraArg; -static int st_list_sort2P(const void *a, const void *b) { - return st_list_sort2_cmpFn(*((char **)a), *((char **)b), st_list_sort2_extraArg); -} - -void stList_sort2(stList *list, int cmpFn(const void *a, const void *b, const void *extraArg), const void *extraArg) { - st_list_sort2_extraArg = extraArg; - st_list_sort2_cmpFn = cmpFn; - qsort(list->list, stList_length(list), sizeof(void *), st_list_sort2P); -} - -void stList_shuffle(stList *list) { - for(int64_t i=0; idestructElement = destructElement; -} - -stList *stList_filter(stList *list, bool(*fn)(void *)) { - stList *list2 = stList_construct(); - for (int64_t i = 0; i < stList_length(list); i++) { - void *o = stList_get(list, i); - if (fn(o)) { - stList_append(list2, o); - } - } - return list2; -} - -stList *stList_filter2(stList *list, bool(*fn)(void *, void *), void *extraArg) { - stList *list2 = stList_construct(); - for (int64_t i = 0; i < stList_length(list); i++) { - void *o = stList_get(list, i); - if (fn(o, extraArg)) { - stList_append(list2, o); - } - } - return list2; -} - -bool filterToExcludeP(void *element, void *set) { - return stSortedSet_search(set, element) == NULL; -} - -stList *stList_filterToExclude(stList *list, stSortedSet *set) { - return stList_filter2(list, filterToExcludeP, set); -} - -bool filterToIncludeP(void *element, void *set) { - return stSortedSet_search(set, element) != NULL; -} - -stList *stList_filterToInclude(stList *list, stSortedSet *set) { - return stList_filter2(list, filterToIncludeP, set); -} - -stList *stList_join(stList *listOfLists) { - stList *joinedList = stList_construct(); - for (int64_t i = 0; i < stList_length(listOfLists); i++) { - stList_appendAll(joinedList, stList_get(listOfLists, i)); - } - return joinedList; -} - -stSortedSet *stList_convertToSortedSet(stList *list) { - stSortedSet *set = stList_getSortedSet(list, NULL); - stSortedSet_setDestructor(set, list->destructElement); - stList_setDestructor(list, NULL); - stList_destruct(list); - return set; -} - -void stList_mapReplace(stList *l, void *(*mapFn)(void *, void *), void *extraArg) { - int64_t j = stList_length(l); - for(int64_t i=0; i - -#define logUnderflowThreshold 7.5 - -static inline double lookup(double x) { - //return log (exp (x) + 1); - assert(x >= 0.00f); - assert(x <= logUnderflowThreshold); - if (x <= 1.00f) - return ((-0.009350833524763f * x + 0.130659527668286f) * x + 0.498799810682272f) * x + 0.693203116424741f; - if (x <= 2.50f) - return ((-0.014532321752540f * x + 0.139942324101744f) * x + 0.495635523139337f) * x + 0.692140569840976f; - if (x <= 4.50f) - return ((-0.004605031767994f * x + 0.063427417320019f) * x + 0.695956496475118f) * x + 0.514272634594009f; - return ((-0.000458661602210f * x + 0.009695946122598f) * x + 0.930734667215156f) * x + 0.168037164329057f; -} - -double stMath_logAdd(double x, double y) { - if (x < y) - return (x == ST_MATH_LOG_ZERO || y - x >= logUnderflowThreshold) ? y : lookup(y - x) + x; - return (y == ST_MATH_LOG_ZERO || x - y >= logUnderflowThreshold) ? x : lookup(x - y) + y; -} - -static inline double lookupExact(double x) { - return log (exp (x) + 1); -} - -double stMath_logAddExact(double x, double y) { - if (x < y) - return (x == ST_MATH_LOG_ZERO || y - x >= logUnderflowThreshold) ? y : lookupExact(y - x) + x; - return (y == ST_MATH_LOG_ZERO || x - y >= logUnderflowThreshold) ? x : lookupExact(x - y) + y; -} diff --git a/C/impl/sonLibNaiveConnectivity.c b/C/impl/sonLibNaiveConnectivity.c deleted file mode 100644 index b9bec73..0000000 --- a/C/impl/sonLibNaiveConnectivity.c +++ /dev/null @@ -1,332 +0,0 @@ -// Naively keeps track of the connected components in an -// undirected graph. Very slow and wasteful. -#include "sonLibGlobalsInternal.h" - -// Data structures - -struct _stNaiveConnectivity { - // Hash to an adjacency list. Edges are only kept in the adjacency - // list belonging the node whose pointer value is smallest. - stHash *nodesToAdjList; - // What it says on the tin. - stNaiveConnectedComponent *connectedComponentCache; -}; - -struct _stNaiveConnectedComponent { - stSet *nodes; - stNaiveConnectedComponent *next; -}; - -struct _stNaiveConnectedComponentIterator { - stNaiveConnectedComponent *cur; -}; - -struct _stNaiveConnectedComponentNodeIterator { - stSetIterator *it; -}; - -// Linked list for storing edges. -struct adjacency { - void *toNode; - // for faster removal of nodes/edges. maybe not worth it, but who - // cares? - struct adjacency *inverse; - struct adjacency *prev; - struct adjacency *next; -}; - -// Destroy an adjacency linked list. -static void adjList_destruct(struct adjacency *adjList) { - assert(adjList == NULL || adjList->prev == NULL); - while (adjList != NULL) { - struct adjacency *next = adjList->next; - free(adjList); - adjList = next; - } -} -stSet *stNaiveConnectedComponent_getNodes(stNaiveConnectedComponent *comp) { - return(comp->nodes); -} - -stNaiveConnectivity *stNaiveConnectivity_construct(void) { - stNaiveConnectivity *connectivity = calloc(1, sizeof(struct _stNaiveConnectivity)); - connectivity->nodesToAdjList = stHash_construct2(NULL, (void (*)(void *)) adjList_destruct); - - return connectivity; -} - -static void invalidateCache(stNaiveConnectivity *connectivity) { - if (connectivity->connectedComponentCache != NULL) { - stNaiveConnectedComponent *curComponent = connectivity->connectedComponentCache; - while (curComponent != NULL) { - stSet_destruct(curComponent->nodes); - stNaiveConnectedComponent *next = curComponent->next; - free(curComponent); - curComponent = next; - } - connectivity->connectedComponentCache = NULL; - } -} - -void stNaiveConnectivity_destruct(stNaiveConnectivity *connectivity) { - invalidateCache(connectivity); - stHash_destruct(connectivity->nodesToAdjList); - free(connectivity); -} - -void stNaiveConnectivity_addNode(stNaiveConnectivity *connectivity, void *node) { - invalidateCache(connectivity); - - assert(stHash_search(connectivity->nodesToAdjList, node) == NULL); - stHash_insert(connectivity->nodesToAdjList, node, NULL); -} - -void stNaiveConnectivity_addEdge(stNaiveConnectivity *connectivity, void *node1, void *node2) { - invalidateCache(connectivity); - - struct adjacency *newEdge1 = malloc(sizeof(struct adjacency)); - struct adjacency *newEdge2 = malloc(sizeof(struct adjacency)); - newEdge1->toNode = node2; - newEdge2->toNode = node1; - newEdge1->inverse = newEdge2; - newEdge2->inverse = newEdge1; - newEdge1->prev = NULL; - newEdge2->prev = NULL; - - struct adjacency *adjList1 = stHash_search(connectivity->nodesToAdjList, node1); - if (adjList1 == NULL) { - newEdge1->next = NULL; - } else { - newEdge1->next = adjList1; - adjList1->prev = newEdge1; - } - stHash_remove(connectivity->nodesToAdjList, node1); - stHash_insert(connectivity->nodesToAdjList, node1, newEdge1); - - struct adjacency *adjList2 = stHash_search(connectivity->nodesToAdjList, node2); - if (adjList2 == NULL) { - newEdge2->next = NULL; - } else { - newEdge2->next = adjList2; - adjList2->prev = newEdge2; - } - stHash_remove(connectivity->nodesToAdjList, node2); - stHash_insert(connectivity->nodesToAdjList, node2, newEdge2); -} - -// Remove and free an edge properly. -static void removeEdgeFromAdjList(stNaiveConnectivity *connectivity, void *node, struct adjacency *adj) { - invalidateCache(connectivity); - - if (adj->next != NULL) { - adj->next->prev = adj->prev; - } - - if (adj->prev != NULL) { - adj->prev->next = adj->next; - } else { - stHash_remove(connectivity->nodesToAdjList, node); - stHash_insert(connectivity->nodesToAdjList, node, adj->next); - } - free(adj); -} -bool stNaiveConnectivity_hasEdge(stNaiveConnectivity *connectivity, void *node1, void *node2) { - struct adjacency *adjList1 = stHash_search(connectivity->nodesToAdjList, node1); - if(!adjList1) return false; - while(adjList1 != NULL) { - if (adjList1->toNode == node2) { - return true; - } - adjList1 = adjList1->next; - } - return false; -} - -void stNaiveConnectivity_removeEdge(stNaiveConnectivity *connectivity, void *node1, void *node2) { - invalidateCache(connectivity); - - struct adjacency *adjList1 = stHash_search(connectivity->nodesToAdjList, node1); - assert(adjList1 != NULL); - assert(stHash_search(connectivity->nodesToAdjList, node2) != NULL); - - while (adjList1 != NULL) { - if (adjList1->toNode == node2) { - break; - } - adjList1 = adjList1->next; - } - - // We can find the link in the other node's adjacency list easily - struct adjacency *adjList2 = adjList1->inverse; - assert(adjList2->inverse == adjList1); - - // Now remove the links from the lists, and free them. - removeEdgeFromAdjList(connectivity, node1, adjList1); - removeEdgeFromAdjList(connectivity, node2, adjList2); -} - -void stNaiveConnectivity_removeNode(stNaiveConnectivity *connectivity, void *node) { - invalidateCache(connectivity); - - struct adjacency *adjList = stHash_search(connectivity->nodesToAdjList, node); - - while (adjList != NULL) { - struct adjacency *next = adjList->next; // Have to do this beforehand -- adjList will be freed by next line! - stNaiveConnectivity_removeEdge(connectivity, node, adjList->toNode); - adjList = next; - } - - stHash_remove(connectivity->nodesToAdjList, node); -} - -// Remove a connected component from the list of connected components -// properly, then free it. -static void removeComponent(stNaiveConnectedComponent **head, stNaiveConnectedComponent *component) { - stNaiveConnectedComponent *curComponent = *head; - assert(curComponent != NULL); - stNaiveConnectedComponent *prevComponent = NULL; - while (curComponent != NULL) { - if (curComponent == component) { - if (prevComponent != NULL) { - prevComponent->next = curComponent->next; - } else { - *head = curComponent->next; - } - stSet_destruct(component->nodes); - free(component); - break; - } - prevComponent = curComponent; - curComponent = curComponent->next; - } -} - -// Compute the connected components, if they haven't been computed -// already since the last modification. -static void computeConnectedComponents(stNaiveConnectivity *connectivity) { - if (connectivity->connectedComponentCache != NULL) { - // Already computed the connected components. - return; - } - - stHashIterator *nodeIt = stHash_getIterator(connectivity->nodesToAdjList); - void *node; - stNaiveConnectedComponent *componentsHead = NULL; - while ((node = stHash_getNext(nodeIt)) != NULL) { - stSet *myNodeSet = stSet_construct(); - stSet_insert(myNodeSet, node); - struct adjacency *adjList = stHash_search(connectivity->nodesToAdjList, node); - if (adjList != NULL) { - while (adjList != NULL) { - stSet_insert(myNodeSet, adjList->toNode); - adjList = adjList->next; - } - } - - // Now go through the existing connected components and see if - // this overlaps any of them. If it's not a full overlap, then - // this set becomes the union, and we continue looking for - // additional overlaps, then this becomes a new connected - // component. If we find that this is a subset of an existing - // component, we can quit early, since we can't possibly add - // to it or any others. - stNaiveConnectedComponent *curComponent = componentsHead; - while (curComponent != NULL) { - stNaiveConnectedComponent *next = curComponent->next; - - // Find out whether our node set is a subset of this - // connected component, or if it shares any overlap. - bool isSubset = true; - bool overlap = false; - stSetIterator *myNodeIt = stSet_getIterator(myNodeSet); - void *node; - while ((node = stSet_getNext(myNodeIt)) != NULL) { - if (stSet_search(curComponent->nodes, node)) { - overlap = true; - } else { - isSubset = false; - } - } - stSet_destructIterator(myNodeIt); - - if (isSubset) { - assert(overlap == true); - // Quit early. - stSet_destruct(myNodeSet); - myNodeSet = NULL; - break; - } else if (overlap) { - stSet *newNodeSet = stSet_getUnion(myNodeSet, curComponent->nodes); - stSet_destruct(myNodeSet); - removeComponent(&componentsHead, curComponent); - myNodeSet = newNodeSet; - } - - curComponent = next; - } - if (myNodeSet != NULL) { - // We have a new (or possibly merged) connected component to - // add to the list. - stNaiveConnectedComponent *newComponent = malloc(sizeof(stNaiveConnectedComponent)); - newComponent->nodes = myNodeSet; - newComponent->next = componentsHead; - componentsHead = newComponent; - } - } - - stHash_destructIterator(nodeIt); - - connectivity->connectedComponentCache = componentsHead; -} - -stNaiveConnectedComponent *stNaiveConnectivity_getConnectedComponent(stNaiveConnectivity - *connectivity, void *node) { - computeConnectedComponents(connectivity); - - stNaiveConnectedComponent *curComponent = connectivity->connectedComponentCache; - while (curComponent != NULL) { - if (stSet_search(curComponent->nodes, node)) { - break; - } - curComponent = curComponent->next; - } - assert(curComponent != NULL); - return curComponent; -} - -stNaiveConnectedComponentNodeIterator *stNaiveConnectedComponent_getNodeIterator(stNaiveConnectedComponent - *component) { - stNaiveConnectedComponentNodeIterator *ret = malloc(sizeof(stNaiveConnectedComponentNodeIterator)); - ret->it = stSet_getIterator(component->nodes); - return ret; -} - -void *stNaiveConnectedComponentNodeIterator_getNext(stNaiveConnectedComponentNodeIterator *it) { - return stSet_getNext(it->it); -} - -void stNaiveConnectedComponentNodeIterator_destruct(stNaiveConnectedComponentNodeIterator *it) { - stSet_destructIterator(it->it); - free(it); -} - -stNaiveConnectedComponentIterator *stNaiveConnectivity_getConnectedComponentIterator(stNaiveConnectivity - *connectivity) { - computeConnectedComponents(connectivity); - - stNaiveConnectedComponentIterator *ret = malloc(sizeof(stNaiveConnectedComponentIterator)); - ret->cur = connectivity->connectedComponentCache; - return ret; -} - -stNaiveConnectedComponent *stNaiveConnectedComponentIterator_getNext(stNaiveConnectedComponentIterator *it) { - stNaiveConnectedComponent *ret = it->cur; - if (ret != NULL) { - it->cur = it->cur->next; - } - return ret; -} - -void stNaiveConnectedComponentIterator_destruct(stNaiveConnectedComponentIterator *it) { - free(it); -} diff --git a/C/impl/sonLibRandom.c b/C/impl/sonLibRandom.c deleted file mode 100644 index f835b3e..0000000 --- a/C/impl/sonLibRandom.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "sonLibGlobalsInternal.h" - -const char *RANDOM_EXCEPTION_ID = "RANDOM_EXCEPTION"; - -void st_randomSeed(int64_t seed) { - srand(seed); -} - -int64_t st_randomInt64(int64_t min, int64_t max) { - int64_t i; - if (min < INT32_MIN && max > INT32_MAX) { //Possible overflow condition, deal with by switching to doubles - i = min + (((double)max) - ((double)min)) * st_random(); - } - else { - if (max - min < 1) { - stThrowNew(RANDOM_EXCEPTION_ID, "Range for random int is not positive, min: %" PRIi64 ", max %" PRIi64 "\n", min, max); - } - i = min + (max - min) * st_random(); - } - if(i >= max) { - //return st_randomInt64(min, max); - i = max-1; - } - assert(i >= min); - assert(i < max); - return i; -} - -int64_t st_randomInt(int64_t min, int64_t max) { - return st_randomInt64(min, max); -} - -double st_random(void) { - static const double i = RAND_MAX+1.0; - double d = rand()/i; - return d >= 1.0 ? 0.9999 : (d < 0.0 ? 0.0 : d); -} - -void *st_randomChoice(stList *list) { - if(stList_length(list) == 0) { - stThrowNew(RANDOM_EXCEPTION_ID, "Can not return a random choice from an empty list\n"); - } - return stList_get(list, st_randomInt(0, stList_length(list))); -} - -char stRandom_getRandomNucleotide(bool includeNs, bool useLowerCase, bool useRandomCase) { - double d = st_random(); - char c = includeNs ? (d >= 0.8 ? 'A' : (d >= 0.6 ? 'T' : (d >= 0.4 ? 'G' : (d >= 0.2 ? 'C' : 'N')))) : - d >= 0.75 ? 'A' : (d >= 0.5 ? 'T' : (d >= 0.25 ? 'G' : 'C')); - return useLowerCase || (useRandomCase && st_random() > 0.5) ? tolower(c) : c; -} - -char *stRandom_getRandomDNAString(int64_t length, bool includeNs, bool useLowerCase, bool useRandomCase) { - char *string = st_malloc(sizeof(char) * (length + 1)); - for (int64_t i = 0; i < length; i++) { - string[i] = stRandom_getRandomNucleotide(includeNs, useLowerCase, useRandomCase); - } - string[length] = '\0'; - return string; -} - diff --git a/C/impl/sonLibSet.c b/C/impl/sonLibSet.c deleted file mode 100644 index b3825b5..0000000 --- a/C/impl/sonLibSet.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2012 by Dent Earl dentearl (a) gmail com - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibSet.c - * - * Created on: 12 July 2012 - * Author: dentearl - */ -#include "sonLibGlobalsInternal.h" -#include "sonLibHash.h" -#include "sonLibSet.h" - -const char *SET_EXCEPTION_ID = "SET_EXCEPTION"; - -struct _stSet { - stHash *hash; -}; -struct _stSetIterator { - stHashIterator *hashIterator; -}; - -uint64_t stSet_pointer(const void *k) { - return (uint64_t) (size_t) k; // Use the low order bits -} -static int stSet_equalKey(const void *key1, const void *key2) { - return key1 == key2; -} -stSet *stSet_construct(void) { - return stSet_construct3(stSet_pointer, stSet_equalKey, NULL); -} -stSet *stSet_construct2(void(*destructKeys)(void *)) { - return stSet_construct3(stSet_pointer, stSet_equalKey, destructKeys); -} -stSet *stSet_construct3(uint64_t(*hashKey)(const void *), int(*hashEqualsKey)(const void *, const void *), void(*destructKeys)(void *)) { - stSet *set = st_malloc(sizeof(*set)); - set->hash = stHash_construct3(hashKey, hashEqualsKey, destructKeys, NULL); - return set; -} -void stSet_destruct(stSet *set) { - stHash_destruct(set->hash); - free(set); -} -void stSet_insert(stSet *set, void *key) { - if (stSet_search(set, key) != NULL) { // This will ensure we don't end up with duplicate keys.. - stSet_remove(set, key); - } - stHash_insert(set->hash, key, key); -} -void stSet_insertAll(stSet *set, stSet *setToAdd) { - stSetIterator *setIt = stSet_getIterator(setToAdd); - void *o; - while((o = stSet_getNext(setIt)) != NULL) { - stSet_insert(set, o); - } - stSet_destructIterator(setIt); -} -void *stSet_search(stSet *set, void *key) { - return stHash_search(set->hash, key); -} -void *stSet_remove(stSet *set, void *key) { - return stHash_remove(set->hash, key); -} -void *stSet_removeAndFreeKey(stSet *set, void *key) { - return stHash_removeAndFreeKey(set->hash, key); -} - -void stSet_removeAll(stSet *set, stSet *subset) { - stSetIterator *it = stSet_getIterator(subset); - - void *o; - while((o = stSet_getNext(it)) != NULL) { - stSet_remove(set, o); - } - stSet_destructIterator(it); -} - -int64_t stSet_size(stSet *set) { - return stHash_size(set->hash); -} -stSetIterator *stSet_getIterator(stSet *set) { - stSetIterator *sit = st_malloc(sizeof(*sit)); - sit->hashIterator = stHash_getIterator(set->hash); - return sit; -} -void *stSet_getNext(stSetIterator *iterator) { - return stHash_getNext(iterator->hashIterator); -} -stSetIterator *stSet_copyIterator(stSetIterator *iterator) { - stSetIterator *iterator2 = st_malloc(sizeof(*iterator2)); - iterator2->hashIterator = stHash_copyIterator(iterator->hashIterator); - return iterator2; -} -void stSet_destructIterator(stSetIterator *iterator) { - stHash_destructIterator(iterator->hashIterator); - free(iterator); -} -stList *stSet_getKeys(stSet *set) { - stList *list = stList_construct(); - stSetIterator *iterator = stSet_getIterator(set); - void *item; - while ((item = stSet_getNext(iterator)) != NULL) { - stList_append(list, item); - } - stSet_destructIterator(iterator); - return list; -} -stList *stSet_getList(stSet *set) { - return stSet_getKeys(set); -} -uint64_t (*stSet_getHashFunction(stSet *set))(const void *) { - return stHash_getHashFunction(set->hash); -} -int (*stSet_getEqualityFunction(stSet *set))(const void *, const void *) { - return stHash_getEqualityFunction(set->hash); -} -void (*stSet_getDestructorFunction(stSet *set))(void *) { - return stHash_getKeyDestructorFunction(set->hash); -} -static int stSet_hashersEqual(stSet *set1, stSet *set2) { - return stSet_getHashFunction(set1) == stSet_getHashFunction(set2); -} -static int stSet_equalitiesEqual(stSet *set1, stSet *set2) { - return stSet_getEqualityFunction(set1) == stSet_getEqualityFunction(set2); -} -void *stSet_peek(stSet *set) { - if(stSet_size(set) == 0) { - stThrowNew(SET_EXCEPTION_ID, "Set is empty."); - } - stSetIterator *setIt = stSet_getIterator(set); - void *object = stSet_getNext(setIt); - stSet_destructIterator(setIt); - return object; -} -static void stSet_verifySetsHaveSameFunctions(stSet *set1, stSet *set2) { - if (!stSet_hashersEqual(set1, set2)) { - stThrowNew(SET_EXCEPTION_ID, "Comparator functions are not equal for " - "two sets."); - } - if (!stSet_equalitiesEqual(set1, set2)) { - stThrowNew(SET_EXCEPTION_ID, "Hash functions are not equal for " - "two sets."); - } -} -stSet *stSet_getUnion(stSet *set1, stSet *set2) { - stSet_verifySetsHaveSameFunctions(set1, set2); - stSet *set3 = stSet_construct3(stSet_getHashFunction(set1), - stSet_getEqualityFunction(set1), - NULL); - // Add everything - stSetIterator *sit= stSet_getIterator(set1); - void *o; - while ((o = stSet_getNext(sit)) != NULL) { - stSet_insert(set3, o); - } - stSet_destructIterator(sit); - sit = stSet_getIterator(set2); - while ((o = stSet_getNext(sit)) != NULL) { - stSet_insert(set3, o); - } - stSet_destructIterator(sit); - return set3; -} -stSet *stSet_getIntersection(stSet *set1, stSet *set2) { - stSet_verifySetsHaveSameFunctions(set1, set2); - stSet *set3 = stSet_construct3(stSet_getHashFunction(set1), - stSet_getEqualityFunction(set1), - NULL); - // Add those from set1 only if they are also in set2 - stSetIterator *sit= stSet_getIterator(set1); - void *o; - while ((o = stSet_getNext(sit)) != NULL) { - if (stSet_search(set2, o) != NULL) { - stSet_insert(set3, o); - } - } - stSet_destructIterator(sit); - return set3; -} -stSet *stSet_getDifference(stSet *set1, stSet *set2) { - stSet_verifySetsHaveSameFunctions(set1, set2); - stSet *set3 = stSet_construct3(stSet_getHashFunction(set1), - stSet_getEqualityFunction(set1), - NULL); - // Add those from set1 only if they are not in set2 - stSetIterator *sit= stSet_getIterator(set1); - void *o; - while ((o = stSet_getNext(sit)) != NULL) { - if (stSet_search(set2, o) == NULL) { - stSet_insert(set3, o); - } - } - stSet_destructIterator(sit); - return set3; -} - -bool stSet_equals(stSet *set1, stSet *set2) { - if(stSet_size(set1) != stSet_size(set2)) { - return 0; - } - stSet *setI = stSet_getIntersection(set1, set2); - bool b = stSet_size(setI) == stSet_size(set1); - stSet_destruct(setI); - return b; -} - -bool stSet_isSubset(stSet *parentSet, stSet *putativeSubset) { - stSet *setI = stSet_getIntersection(parentSet, putativeSubset); - bool b = stSet_size(setI) == stSet_size(putativeSubset); - stSet_destruct(setI); - return b; -} diff --git a/C/impl/sonLibSortedSet.c b/C/impl/sonLibSortedSet.c deleted file mode 100644 index 404343b..0000000 --- a/C/impl/sonLibSortedSet.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "sonLibGlobalsInternal.h" -#include "avl.h" - -const char *SORTED_SET_EXCEPTION_ID = "SORTED_SET_EXCEPTION"; - -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//Functions on a sorted set and its iterator -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// - -struct _stSortedSet { - struct avl_table *sortedSet; - void (*destructElementFn)(void *); - int numberOfLiveIterators; // number of currently allocated iterators -}; - -struct _stSortedSetIterator { - stSortedSet *sortedSet; - struct avl_traverser traverser; -}; - -static int st_sortedSet_cmpFn( const void *key1, const void *key2 ) { - return key1 > key2 ? 1 : key1 < key2 ? -1 : 0; -} - -/* check if the sorted set is in a state that it can be modified */ -static void checkModifiable(stSortedSet *sortedSet) { - if (sortedSet->numberOfLiveIterators > 0) { - //assert(0); - stThrowNew(SORTED_SET_EXCEPTION_ID, "attempt to modify an stSortedSet while iterators are active"); - } -} - -stSortedSet *stSortedSet_construct(void) { - return stSortedSet_construct3(st_sortedSet_cmpFn, NULL); -} - -stSortedSet *stSortedSet_construct2(void (*destructElementFn)(void *)) { - return stSortedSet_construct3(st_sortedSet_cmpFn, destructElementFn); -} - -struct _stSortedSet_construct3Fn { - int (*compareFn)(const void *, const void *); -}; - -static int st_sortedSet_construct3P(const void *a, const void *b, struct _stSortedSet_construct3Fn *c) { //int (*cmpFn)(const void *, const void *)) { - return c->compareFn(a, b); -} - -stSortedSet *stSortedSet_construct3(int (*compareFn)(const void *, const void *), - void (*destructElementFn)(void *)) { - stSortedSet *sortedSet = st_malloc(sizeof(stSortedSet)); - struct _stSortedSet_construct3Fn *i = st_malloc(sizeof(struct _stSortedSet_construct3Fn)); - i->compareFn = compareFn == NULL ? st_sortedSet_cmpFn : compareFn; //this is a total hack to make the function pass ISO C compatible. - sortedSet->sortedSet = avl_create((int (*)(const void *, const void *, void *))st_sortedSet_construct3P, i, NULL); - sortedSet->destructElementFn = destructElementFn; - sortedSet->numberOfLiveIterators = 0; - return sortedSet; -} - -void stSortedSet_setDestructor(stSortedSet *set, void (*destructElement)(void *)) { - set->destructElementFn = destructElement; -} - -static struct _stSortedSet_construct3Fn *stSortedSet_getComparator(stSortedSet *sortedSet) { - return (struct _stSortedSet_construct3Fn *)sortedSet->sortedSet->avl_param; -} - -stSortedSet *stSortedSet_copyConstruct(stSortedSet *sortedSet, void (*destructElementFn)(void *)) { - stSortedSet *sortedSet2 = stSortedSet_construct3(stSortedSet_getComparator(sortedSet)->compareFn, destructElementFn); - stSortedSetIterator *it = stSortedSet_getIterator(sortedSet); - void *o; - while((o = stSortedSet_getNext(it)) != NULL) { - stSortedSet_insert(sortedSet2, o); - } - stSortedSet_destructIterator(it); - return sortedSet2; -} - -static void (*st_sortedSet_destruct_destructElementFn)(void *); -static void st_sortedSet_destructP(void *a, void *b) { - assert(b != NULL); - st_sortedSet_destruct_destructElementFn(a); -} - -void stSortedSet_destruct(stSortedSet *sortedSet) { -#if 0 // FIXME - // this breaks the tests, which leak iterators. Need to revisit with - // Benedict and also figure out how to tests this. In the mean time, - // this is for an urgent bug. - checkModifiable(sortedSet); -#endif - void *a = sortedSet->sortedSet->avl_param; - if(sortedSet->destructElementFn != NULL) { - st_sortedSet_destruct_destructElementFn = sortedSet->destructElementFn; - avl_destroy(sortedSet->sortedSet, (void (*)(void *, void *))st_sortedSet_destructP); - } - else { - avl_destroy(sortedSet->sortedSet, NULL); - } - free(a); - free(sortedSet); -} - -void stSortedSet_insert(stSortedSet *sortedSet, void *object) { - checkModifiable(sortedSet); - // FIXME: two passes, modify avl code. - if(stSortedSet_search(sortedSet, object) != NULL) { - avl_replace(sortedSet->sortedSet, object); - } - else { - avl_insert(sortedSet->sortedSet, object); - } -} - -void *stSortedSet_search(stSortedSet *sortedSet, void *object) { - return avl_find(sortedSet->sortedSet, object); -} - -void *stSortedSet_searchLessThanOrEqual(stSortedSet *sortedSet, void *object) { - return avl_find_lessThanOrEqual(sortedSet->sortedSet, object); -} - -void *stSortedSet_searchLessThan(stSortedSet *sortedSet, void *object) { - return avl_find_lessThan(sortedSet->sortedSet, object); -} - -void *stSortedSet_searchGreaterThanOrEqual(stSortedSet *sortedSet, void *object) { - return avl_find_greaterThanOrEqual(sortedSet->sortedSet, object); -} - -void *stSortedSet_searchGreaterThan(stSortedSet *sortedSet, void *object) { - return avl_find_greaterThan(sortedSet->sortedSet, object); -} - -void *stSortedSet_remove(stSortedSet *sortedSet, void *object) { - checkModifiable(sortedSet); - return avl_delete(sortedSet->sortedSet, object); -} - -int64_t stSortedSet_size(stSortedSet *sortedSet) { - return avl_count(sortedSet->sortedSet); -} - -void *stSortedSet_getFirst(stSortedSet *items) { - struct avl_traverser traverser; - avl_t_init(&traverser, items->sortedSet); - return avl_t_first(&traverser, items->sortedSet); -} - -void *stSortedSet_getLast(stSortedSet *items) { - struct avl_traverser traverser; - avl_t_init(&traverser, items->sortedSet); - return avl_t_last(&traverser, items->sortedSet); -} - -stSortedSetIterator *stSortedSet_getIterator(stSortedSet *items) { - stSortedSetIterator *iterator; - iterator = st_malloc(sizeof(stSortedSetIterator)); - iterator->sortedSet = items; - avl_t_init(&iterator->traverser, items->sortedSet); - items->numberOfLiveIterators++; - return iterator; -} - -stSortedSetIterator *stSortedSet_getIteratorFrom(stSortedSet *items, void *item) { - stSortedSetIterator *iterator = stSortedSet_getIterator(items); - if(avl_t_find(&iterator->traverser, items->sortedSet, item) == NULL) { - stSortedSet_destructIterator(iterator); - stThrowNew(SORTED_SET_EXCEPTION_ID, "Tried to create an iterator with an item that is not in the list of items"); - } - stSortedSet_getPrevious(iterator); - return iterator; -} - -stSortedSetIterator *stSortedSet_getReverseIterator(stSortedSet *items) { - stSortedSetIterator *it = stSortedSet_getIteratorFrom(items, stSortedSet_getLast(items)); - stSortedSet_getNext(it); - stSortedSet_getNext(it); - return it; -} - -void stSortedSet_destructIterator(stSortedSetIterator *iterator) { - assert(iterator->sortedSet->numberOfLiveIterators > 0); - iterator->sortedSet->numberOfLiveIterators--; - free(iterator); -} - -void *stSortedSet_getNext(stSortedSetIterator *iterator) { - return avl_t_next(&iterator->traverser); -} - -stSortedSetIterator *stSortedSet_copyIterator(stSortedSetIterator *iterator) { - stSortedSetIterator *copyIterator; - copyIterator = st_malloc(sizeof(stSortedSetIterator)); - copyIterator->sortedSet = iterator->sortedSet; - copyIterator->sortedSet->numberOfLiveIterators++; - avl_t_copy(©Iterator->traverser, &iterator->traverser); - return copyIterator; -} - -void *stSortedSet_getPrevious(stSortedSetIterator *iterator) { - return avl_t_prev(&iterator->traverser); -} - -static int stSortedSet_comparatorsEqual(stSortedSet *sortedSet1, stSortedSet *sortedSet2) { - return stSortedSet_getComparator(sortedSet1)->compareFn == stSortedSet_getComparator(sortedSet2)->compareFn; -} - -int stSortedSet_equals(stSortedSet *sortedSet1, stSortedSet *sortedSet2) { - if(stSortedSet_size(sortedSet1) != stSortedSet_size(sortedSet2)) { - return 0; - } - if(!stSortedSet_comparatorsEqual(sortedSet1, sortedSet2)) { - return 0; - } - int (*cmpFn)(const void *, const void *) = stSortedSet_getComparator(sortedSet1)->compareFn; - - stSortedSetIterator *it1 = stSortedSet_getIterator(sortedSet1); - stSortedSetIterator *it2 = stSortedSet_getIterator(sortedSet2); - void *o1 = stSortedSet_getNext(it1), *o2 = stSortedSet_getNext(it2); - while(o1 != NULL && o2 != NULL) { - if(cmpFn(o1, o2) != 0) { - stSortedSet_destructIterator(it1); - stSortedSet_destructIterator(it2); - return 0; - } - o1 = stSortedSet_getNext(it1); - o2 = stSortedSet_getNext(it2); - } - stSortedSet_destructIterator(it1); - stSortedSet_destructIterator(it2); - return 1; -} - -stList *stSortedSet_getList(stSortedSet *sortedSet) { - stList *list = stList_construct2(stSortedSet_size(sortedSet)); - stSortedSetIterator *it = stSortedSet_getIterator(sortedSet); - void *o; - int64_t i=0; - while((o = stSortedSet_getNext(it)) != NULL) { - stList_set(list, i++, o); - } - assert(i == stSortedSet_size(sortedSet)); - stSortedSet_destructIterator(it); - return list; -} - -stSortedSet *stSortedSet_getUnion(stSortedSet *sortedSet1, stSortedSet *sortedSet2) { - if(!stSortedSet_comparatorsEqual(sortedSet1, sortedSet2)) { - stThrowNew(SORTED_SET_EXCEPTION_ID, "Comparators are not equal for creating the union of two sorted sets"); - } - stSortedSet *sortedSet3 = stSortedSet_construct3(stSortedSet_getComparator(sortedSet1)->compareFn, NULL); - - //Add those from sortedSet1 - stSortedSetIterator *it= stSortedSet_getIterator(sortedSet1); - void *o; - while((o = stSortedSet_getNext(it)) != NULL) { - stSortedSet_insert(sortedSet3, o); - } - stSortedSet_destructIterator(it); - - //Add those from sortedSet2 - it= stSortedSet_getIterator(sortedSet2); - while((o = stSortedSet_getNext(it)) != NULL) { - stSortedSet_insert(sortedSet3, o); - } - stSortedSet_destructIterator(it); - - return sortedSet3; -} - -stSortedSet *stSortedSet_getIntersection(stSortedSet *sortedSet1, stSortedSet *sortedSet2) { - if(!stSortedSet_comparatorsEqual(sortedSet1, sortedSet2)) { - stThrowNew(SORTED_SET_EXCEPTION_ID, "Comparators are not equal for creating an intersection of two sorted sets"); - } - stSortedSet *sortedSet3 = stSortedSet_construct3(stSortedSet_getComparator(sortedSet1)->compareFn, NULL); - - //Add those from sortedSet1 only if they are also in sortedSet2 - stSortedSetIterator *it= stSortedSet_getIterator(sortedSet1); - void *o; - while((o = stSortedSet_getNext(it)) != NULL) { - if(stSortedSet_search(sortedSet2, o) != NULL) { - stSortedSet_insert(sortedSet3, o); - } - } - stSortedSet_destructIterator(it); - - return sortedSet3; -} - -stSortedSet *stSortedSet_getDifference(stSortedSet *sortedSet1, stSortedSet *sortedSet2) { - if(!stSortedSet_comparatorsEqual(sortedSet1, sortedSet2)) { - stThrowNew(SORTED_SET_EXCEPTION_ID, "Comparators are not equal for creating the sorted set difference"); - } - stSortedSet *sortedSet3 = stSortedSet_construct3(stSortedSet_getComparator(sortedSet1)->compareFn, NULL); - - //Add those from sortedSet1 only if they are not in sortedSet2 - stSortedSetIterator *it= stSortedSet_getIterator(sortedSet1); - void *o; - while((o = stSortedSet_getNext(it)) != NULL) { - if(stSortedSet_search(sortedSet2, o) == NULL) { - stSortedSet_insert(sortedSet3, o); - } - } - stSortedSet_destructIterator(it); - - return sortedSet3; -} diff --git a/C/impl/sonLibString.c b/C/impl/sonLibString.c deleted file mode 100644 index 264fbd8..0000000 --- a/C/impl/sonLibString.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibString.c - * - * Created on: 24-May-2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsInternal.h" - -char *stString_copy(const char *string) { - if (string == NULL) { - return NULL; - } else { - return strcpy(st_malloc(sizeof(char)*(1+strlen(string))), string); - } -} - -char *stString_print(const char *string, ...) { - int64_t arraySize = 0; - static char *cA = NULL; - //return; - va_list ap; - va_start(ap, string); - int64_t i = vsnprintf(cA, arraySize, string, ap); - va_end(ap); - assert(i >= 0); - if(i >= arraySize) { - arraySize = i+1; - if(cA != NULL) { - free(cA); - } - cA = st_malloc(sizeof(char) * arraySize); - va_start(ap, string); - i = vsnprintf(cA, arraySize, string, ap); - assert(i+1 == arraySize); - va_end(ap); - } - //vfprintf(stdout, string, ap); - return stString_copy(cA); -} - -char *stString_print_r(const char *string, ...) { - va_list ap; - va_start(ap, string); - int64_t i = vsnprintf(NULL, 0, string, ap); - va_end(ap); - - assert(i >= 0); - int64_t arraySize = i + 1; - char *ret = st_malloc(sizeof(char) * arraySize); - va_start(ap, string); - i = vsnprintf(ret, arraySize, string, ap); - assert(i+1 == arraySize); - va_end(ap); - - return ret; -} - -char *stString_getNextWord(char **string) { - while(**string != '\0' && isspace(**string)) { - (*string)++; - } - char *i = *string; - while(**string != '\0' && !isspace(**string)) { - (*string)++; - } - if((*string) - i > 0) { - char *cA = memcpy(st_malloc(((*string)-i + 1)*sizeof(char)), i, ((*string)-i)*sizeof(char)); - cA[(*string) - i] = '\0'; - return cA; - } - return NULL; -} - -static int64_t string_replaceP(char *start, const char *pattern) { - uint64_t i; - for(i=0; i 0); //Must be non zero length replacement string. - j=0; - i=(char *)originalString; - while(*i != '\0') { - if(string_replaceP(i, toReplace)) { - j++; - i += strlen(toReplace); - } - else { - i++; - } - } - newString = st_malloc(sizeof(char)*(strlen(originalString) + j*strlen(replacement) - j*strlen(toReplace) + 1)); - k=newString; - i=(char *)originalString; - while(*i != '\0') { - if(string_replaceP(i, toReplace)) { - for(j=0; j= 0); - int64_t j = padLength * (length > 0 ? length - 1 : 0) + 1; - for(int64_t i=0; ilist, stList_length(strings)); -} - -stList *stString_split(const char *string) { - char *cA = stString_copy(string); - char *cA2 = cA; - char *token; - stList *tokens = stList_construct3(0, free); - while((token = stString_getNextWord(&cA)) != NULL) { - stList_append(tokens, token); - } - free(cA2); - return tokens; -} - -stList *stString_splitByString(const char *string, const char *delim) { - const char *curTokenStart = string; - const char *curTokenEnd; - size_t tokenLength = strlen(delim); - assert(tokenLength > 0); - stList *ret = stList_construct3(0, free); - while ((curTokenEnd = strstr(curTokenStart, delim)) != NULL) { - stList_append(ret, stString_getSubString(curTokenStart, 0, curTokenEnd - curTokenStart)); - curTokenStart = curTokenEnd + tokenLength; - } - stList_append(ret, stString_copy(curTokenStart)); - - return ret; -} - -char *stString_getSubString(const char *cA, int64_t start, int64_t length) { - char *cA2 = memcpy(st_malloc(sizeof(char) * (length + 1)), cA + start, length); - cA2[length] = '\0'; - return cA2; -} - -static char correctCase(char newChar, char oldChar) { - return toupper(oldChar) == oldChar ? toupper(newChar) : tolower(newChar); -} - -char stString_reverseComplementChar(char c) { - switch (c) { - case 'a': - case 'A': - return correctCase('t', c); - case 'c': - case 'C': - return correctCase('g', c); - case 'g': - case 'G': - return correctCase('c', c); - case 't': - case 'T': - return correctCase('a', c); - - //Two redundant characters - case 'w': - case 'W': - case 's': - case 'S': - return c; //Complement is the same for S and W - - case 'M': - case 'm': - return correctCase('k', c); //Complement is k - case 'k': - case 'K': - return correctCase('m', c); //Complement is m - - case 'r': - case 'R': - return correctCase('y', c); //Complement is y - case 'y': - case 'Y': - return correctCase('r', c); //Complement is r - - //Three redundant characters - case 'b': - case 'B': - return correctCase('v', c); //Complement is v - case 'v': - case 'V': - return correctCase('b', c); //Complement is b - - case 'd': - case 'D': - return correctCase('h', c); //Complement is h - case 'h': - case 'H': - return correctCase('d', c); //Complement is d - - default: //Includes N, but also any other character. - return c; - } -} - -char *stString_reverseComplementString(const char *string) { - int64_t i, j; - - j = strlen(string); - char *cA; - - cA = st_malloc(sizeof(char) * (j + 1)); - for (i = 0; i < j; i++) { - cA[i] = stString_reverseComplementChar(string[j - 1 - i]); - } - cA[j] = '\0'; - return cA; -} diff --git a/C/impl/sonLibTreap.c b/C/impl/sonLibTreap.c deleted file mode 100644 index 1dd619a..0000000 --- a/C/impl/sonLibTreap.c +++ /dev/null @@ -1,524 +0,0 @@ -#include "sonLibGlobalsInternal.h" -/*Implementation of a balanced binary tree. The binary tree property is maintained with - * respect to the keys, while the heap property is maintained for the priority values, which - * are generated randomly for each element as it is inserted into the tree. The randomized - * priority values make the treap highly likely to be balanced. */ - - -stTreap *stTreap_construct(void *value) { - //strand(time(0)); - stTreap *node = st_malloc(sizeof(stTreap)); - node->key = 0; - node->priority = rand(); - node->left = node->right = node->parent = NULL; - node->count = 1; - node->value = value; - return(node); -} -void *stTreap_getValue(stTreap *node) { - return(node->value); -} -void stTreap_destructRecurse(stTreap *root) { - if(root->left) { - stTreap_destructRecurse(root->left); - } - if(root->right) { - stTreap_destructRecurse(root->right); - } - //free(root->value); - free(root); -} -void stTreap_destruct(stTreap *node) { - node = stTreap_findRoot(node); - stTreap_destructRecurse(node); -} -void stTreap_nodeDestruct(stTreap *node) { - free(node); -} -char *stTreap_print(stTreap *node) { - node = stTreap_findRoot(node); - node = stTreap_findMin(node); - char *path = st_calloc(stTreap_size(node) + 1, 1); - while(node) { - strcat(path, node->value); - node = stTreap_next(node); - } - return(path); -} -char *stTreap_printBackwards(stTreap *node) { - node = stTreap_findRoot(node); - node = stTreap_findMax(node); - char *path = st_calloc(stTreap_size(node) + 1, 1); - while(node) { - strcat(path, node->value); - node = stTreap_prev(node); - } - return(path); -} - - -/*Left tree rotation at node u, which preserves the in-order traversal: - * - * p p - * / / - * u w - * / \ -----> / \ - * a w u c - * / \ / \ - * b c a b - * - */ -void stTreap_rotateLeft(stTreap *u) { - stTreap *w = u->right; - if(!w) return; - w->parent = u->parent; - if(w->parent) { - if(w->parent->left == u) { - w->parent->left = w; - } - else { - w->parent->right = w; - } - } - u->right = w->left; - if(u->right) { - u->right->parent = u; - } - u->parent = w; - w->left = u; - - - u->count -= w->count; - if(u->right) { - u->count += u->right->count; - w->count -= u->right->count; - } - w->count += u->count; -} - -/*Right tree rotation at node u: - * p p - * / / - * u w - * / \ / \ - * w c ----> a u - * / \ / \ - * a b b c - * - */ -void stTreap_rotateRight(stTreap *u) { - stTreap *w = u->left; - assert(w); - w->parent = u->parent; - if(w->parent) { - if(w->parent->left == u) { - w->parent->left = w; - } - else { - w->parent->right = w; - } - } - u->left = w->right; - if(u->left) { - u->left->parent = u; - } - u->parent = w; - w->right = u; - - u->count -= w->count; - if(u->left) { - u->count += u->left->count; - w->count -= u->left->count; - } - w->count += u->count; - -} -stTreap *stTreap_findRoot(stTreap *node) { - while(node->parent) { - node = node->parent; - } - return(node); -} - -int stTreap_size(stTreap *node) { - node = stTreap_findRoot(node); - return(node->count); -} - -/*Finds the closest node to the given key using a binary search. */ -stTreap *stTreap_binarySearch(long key, stTreap *node) { - node = stTreap_findRoot(node); - while(1) { - if(key == node->key) { - break; - } - else if(key < node->key) { - if(node->left) { - node = node->left; - } - else { - break; - } - } - else { - if(node->right) { - node = node->right; - } - else { - break; - } - } - } - return(node); -} - -/* Returns true of the given tree contains the given node. */ -int stTreap_contains(stTreap *tree, stTreap *node) { - stTreap *closestNode = stTreap_binarySearch(node->key, tree); - return(closestNode->key == node->key); -} -int stTreap_depth(stTreap *node) { - int depth = 0; - while(node->parent) { - node = node->parent; - depth++; - } - return(depth); -} - -/*compares two nodes without using their keys. O(lgn) */ -int stTreap_compare(stTreap* a, stTreap *b) { - if (a == b) { - return 0; - } - assert(stTreap_findRoot(a) == stTreap_findRoot(b)); - int depthA = stTreap_depth(a); - int depthB = stTreap_depth(b); - - while (depthA > depthB) { - if (a->parent == b) { - if (a == b->left) { - return -1; - } else { - assert(a == b->right); - return 1; - } - } - a = a->parent; - depthA--; - - } - while (depthB > depthA) { - if (b->parent == a) { - if (b == a->left) { - return 1; - } else { - assert(b == a->right); - return -1; - } - } - b = b->parent; - depthB--; - } - assert(depthA == depthB); - int depth = depthA; - while (depth) { - assert(a != b); - if (a->parent == b->parent) { - if (a == a->parent->left) { - assert(b == a->parent->right); - return -1; - } else { - assert(b == a->parent->left); - assert(a == a->parent->right); - return 1; - } - } - a = a->parent; - b = b->parent; - depth--; - } - assert(a && b); - assert(!a->parent); - assert(!b->parent); - return 0; -} - - -/*Restores the heap property by using tree - * rotations to move a new node up until - * its priority is less than that of its parent.*/ -void stTreap_moveUp(stTreap *node) { - while(node->parent && (node->priority >= node->parent->priority)) { - if(node->parent->left == node) { - stTreap_rotateRight(node->parent); - - } - else { - stTreap_rotateLeft(node->parent); - } - } -} - - -/*Insert new key-value pair into the treap at the position determined by - * a binary search for the key. Then restore the heap property. */ -stTreap *stTreap_insert(long key, void *value, stTreap *node) { - node = stTreap_findRoot(node); - stTreap *newNode = stTreap_construct(value); - newNode->key = key; - - stTreap *parent = stTreap_binarySearch(key, node); - if(parent->key == key) { - //duplicate - free(newNode); - return(parent); - } - newNode->parent = parent; - if(key < parent->key) { - parent->left = newNode; - } - else { - parent->right = newNode; - } - - //update counts for all parents of this node - while(parent) { - parent->count += 1; - parent = parent->parent; - } - - stTreap_moveUp(newNode); - return(newNode); -} - -/*Perform rotations to make a node into a leaf, which - * allows it to be deleted without violating the heap property. */ -void stTreap_moveDown(stTreap *node) { - while(node->left || node->right) { - if(!node->left) { - stTreap_rotateLeft(node); - } - else if(!node->right) { - stTreap_rotateRight(node); - } - else if(node->left->priority < node->right->priority) { - stTreap_rotateRight(node); - } - else { - stTreap_rotateLeft(node); - } - } -} -int stTreap_remove(long key, stTreap *tree) { - tree = stTreap_findRoot(tree); - stTreap *rmnode = stTreap_binarySearch(key, tree); - if(rmnode->key != key) { - //key not in the treap - return(0); - } - stTreap_moveDown(rmnode); - if(rmnode->parent) { - if(rmnode->parent->left == rmnode) { - rmnode->parent->left = NULL; - } - else { - rmnode->parent->right = NULL; - } - } - free(rmnode); - //update parent counts - stTreap *p = rmnode->parent; - while(p) { - p->count -= 1; - p = p->parent; - } - //successfully deleted the node - return(1); -} - -/*The node with the minimum key is stored as the leftmost leaf */ -stTreap *stTreap_findMin(stTreap *node) { - assert(node); - while(node->left) { - node = node->left; - } - return(node); -} -stTreap *stTreap_findMax(stTreap *node) { - while(node->right) { - node = node->right; - } - return(node); -} -/*splits the treap containing a node into two treaps, one whose - * keys are all less than that of the node, and one whose keys are all - * greater. Leaves the left subtree connected to the split point node, - * but disconnects the right subtree. Returns the right subtree.*/ -stTreap *stTreap_splitAfter(stTreap *node) { - node->priority = INT_MAX; - stTreap_moveUp(node); - assert(stTreap_findRoot(node) == node); - assert(node->parent == NULL); //node should now be the new root of the treap - stTreap *rightSubtree = node->right; - if(rightSubtree) { - node->count -= rightSubtree->count; - rightSubtree->parent = NULL; - node->right = NULL; - } - stTreap_chooseNewPriority(node); - return(rightSubtree); -} - -/*same as splitAfter, but returns the left subtree.*/ -stTreap *stTreap_splitBefore(stTreap *node) { - node->priority = INT_MAX; - stTreap_moveUp(node); - assert(node); - assert(stTreap_findRoot(node) == node); - assert(node->parent == NULL); - stTreap *leftSubtree = node->left; - if(leftSubtree) { - node->count -= leftSubtree->count; - leftSubtree->parent = NULL; - node->left = NULL; - } - stTreap_chooseNewPriority(node); - return(leftSubtree); -} -//choose a priority value for a node after moving it to the root -void stTreap_chooseNewPriority(stTreap *node) { - int pleft = 0; - int pright = 0; - if (node->left) { - pleft = node->left->priority; - } - if (node->right) { - pright = node->right->priority; - } - if (pleft > pright) { - node->priority = pleft + 1; - } - else { - node->priority = pright + 1; - } -} - -/*returns the next node in an in-order traversal of the treap - * starting at node. */ -stTreap *stTreap_next(stTreap *node) { - assert(node); - if(node->right != NULL) { - return(stTreap_findMin(node->right)); - } - stTreap *p = node->parent; - while(p != NULL && (node == p->right)) { - node = p; - p = p->parent; - } - return(p); -} -stTreap *stTreap_prev(stTreap *node) { - assert(node); - if(node->left) { - return(stTreap_findMax(node->left)); - } - stTreap *p = node->parent; - while(p && (node == p->left)) { - node = p; - p = p->parent; - } - return(p); -} - - -stTreap *stTreap_concat(stTreap *a, stTreap *b) { - if(!a || !b) { - return(NULL); - } - stTreap *ra = stTreap_findRoot(a); - //stTreap *ta = ra; - - //move to largest element in a - //while(ta->right) { - // ta = ta->right; - //} - stTreap *rb = stTreap_findRoot(b); - - //a and b shouldn't already be concatenated - assert(rb != ra); - //stTreap *sb = rb; - - //move to smallest element in b - //while(sb->left) { - // sb = sb->left; - //} - stTreap *r = stTreap_concatRecurse(ra, rb); - r->parent = NULL; - return(r); -} - -/* Joins two treaps, preserving the heap property for priorities and the key orderings, - * assuming that all elements in the left tree are smaller than all elements in the right tree. - * This will be true if the trees were produced by splitting a treap. - * - * d10 x8 - * / \ / \ - * b7 e5 + w6 z4 (Here, keys are letters and priorities - * / \ / are numbers) - * a3 c2 y1 - * - * concatRecurse(d10, x8) - * - * d10 - * / \ - * / \ - * b7 x8 In-order traversal: abcdewxyz - * / \ / \ - * a3 c2 w6 z4 - * / / - * e5 y1 - * - * concatRecurse(e5, x8) - * x8 - * / \ - * w6 z4 - * / / - * e5 y1 - * - * concatRecurse(e5, w6) - * w6 - * / - * e5 - * concatRecurse(e5, NULL) - * - * e5 - * - */ -stTreap *stTreap_concatRecurse(stTreap *a, stTreap *b) { - if (!a) { - return(b); - } - else if (!b) { - return(a); - } - else if (a->priority > b->priority) { - if(a->right) { - a->count -= a->right->count; - } - a->right = stTreap_concatRecurse(a->right, b); - a->count += a->right->count; - a->right->parent = a; - return(a); - } - else { - if(b->left) { - b->count -= b->left->count; - } - - b->left = stTreap_concatRecurse(a, b->left); - b->count += b->left->count; - b->left->parent = b; - return(b); - } -} diff --git a/C/impl/sonLibTree.c b/C/impl/sonLibTree.c deleted file mode 100644 index 88b080f..0000000 --- a/C/impl/sonLibTree.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * tree.c - * - * Created on: 21 May 2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsInternal.h" -#include -#include "sonLibString.h" - -/* - * The actual datastructure. - */ - -struct _stTree { - double branchLength; - stList *nodes; - char *label; - void *clientData; - stTree *parent; -}; - -/* - * The functions.. - */ - -stTree *stTree_construct(void) { - stTree *tree = st_malloc(sizeof(stTree)); - tree->branchLength = INFINITY; - tree->nodes = stList_construct3(0, (void (*)(void *))stTree_destruct); - tree->label = NULL; - tree->parent = NULL; - tree->clientData = NULL; - return tree; -} - -void stTree_destruct(stTree *tree) { - stList_destruct(tree->nodes); - if(tree->label != NULL) { - free(tree->label); - } - free(tree); -} - -/* clone a node */ -stTree *stTree_cloneNode(stTree *node) { - stTree *node2 = stTree_construct(); - stTree_setBranchLength(node2, stTree_getBranchLength(node)); - stTree_setClientData(node2, stTree_getClientData(node)); - stTree_setLabel(node2, stTree_getLabel(node)); - return node2; -} - -/* recursively clone a tree */ -static stTree *tree_clonetree(stTree *node, stTree *parent2) { - stTree *node2 = stTree_cloneNode(node); - stTree_setParent(node2, parent2); - for (int i = 0; i < stTree_getChildNumber(node); i++) { - tree_clonetree(stTree_getChild(node, i), node2); - } - return node2; -} - -stTree *stTree_clone(stTree *root) { - return tree_clonetree(root, NULL); -} - -// Set client data to NULL (optionally recursively). -static void stTree_clearClientData(stTree *tree, bool recursive) { - stTree_setClientData(tree, NULL); - if (recursive) { - for (int64_t i = 0; i < stTree_getChildNumber(tree); i++) { - stTree_clearClientData(stTree_getChild(tree, i), true); - } - } -} - -// clone this node, make its supertree a child, and clone all children -// other than oldNode, leaving this node as a child of nodeToAddTo -static void tree_cloneFlippedTree(stTree *node, stTree *oldNode, - stTree *nodeToAddTo, - double branchLength) { - if(stTree_getParent(node) != NULL || stTree_getChildNumber(node) > 2) { - // This node isn't the root - stTree *clonedNode = stTree_cloneNode(node); - stTree_setParent(clonedNode, nodeToAddTo); - stTree_setBranchLength(clonedNode, branchLength); - // Clone its children (other than oldNode) and their subtrees - for(int64_t i = 0; i < stTree_getChildNumber(node); i++) { - stTree *child = stTree_getChild(node, i); - if(child != oldNode) { - stTree *clonedChild = stTree_clone(child); - stTree_setParent(clonedChild, clonedNode); - } - } - - if (stTree_getParent(node) != NULL) { - // Recurse on the parent of this node. - tree_cloneFlippedTree(stTree_getParent(node), node, - clonedNode, stTree_getBranchLength(node)); - } - } else if (stTree_getParent(node) == NULL) { - // We have to treat the root specially in binary trees, - // because we're going to eliminate it. Just add all the other - // children of the root as children of nodeToAddTo. - for(int64_t i = 0; i < stTree_getChildNumber(node); i++) { - stTree *child = stTree_getChild(node, i); - if(child != oldNode) { - stTree *clonedChild = stTree_clone(child); - stTree_setParent(clonedChild, nodeToAddTo); - stTree_setBranchLength(clonedChild, stTree_getBranchLength(child) + branchLength); - } - } - } -} - -// Return a new tree rooted a given distance above the given node. -static stTree *stTree_reRootP(stTree *node, double distanceAbove, bool clearClientData) { - if(stTree_getParent(node) == NULL) { - // This node is already the root. - stTree *newRoot = stTree_clone(node); - if (clearClientData) { - stTree_clearClientData(newRoot, true); - } - return newRoot; - } - - assert(stTree_getBranchLength(node) >= distanceAbove); - - stTree *newRoot = stTree_construct(); - // This node and its children (if any) are fine already. - stTree *clonedNode = stTree_clone(node); - stTree_setParent(clonedNode, newRoot); - stTree_setBranchLength(clonedNode, distanceAbove); - tree_cloneFlippedTree(stTree_getParent(node), node, newRoot, - stTree_getBranchLength(node) - distanceAbove); - // Having the same client data can be a problem - if (clearClientData) { - stTree_clearClientData(newRoot, true); - } - return newRoot; -} - -stTree *stTree_reRoot(stTree *node, double distanceAbove) { - return stTree_reRootP(node, distanceAbove, true); -} - -stTree *stTree_reRootAndKeepClientData(stTree *node, double distanceAbove) { - return stTree_reRootP(node, distanceAbove, false); -} - -stTree *stTree_getParent(stTree *tree) { - return tree->parent; -} - -void stTree_setParent(stTree *tree, stTree *parent) { - if(stTree_getParent(tree) != NULL) { - stList_removeItem(stTree_getParent(tree)->nodes, tree); - } - tree->parent = parent; - if(parent != NULL) { - stList_append(parent->nodes, tree); - } -} - -int64_t stTree_getChildNumber(stTree *tree) { - return stList_length(tree->nodes); -} - -stTree *stTree_getChild(stTree *tree, int64_t i) { - return stList_get(tree->nodes, i); -} - -stTree *stTree_findChild(stTree *tree, const char *label) { - if (tree->label != NULL && strcmp(tree->label, label) == 0) { - return tree; - } - for (int i = 0; i < stList_length(tree->nodes); i++) { - stTree *node = (stTree *)stList_get(tree->nodes, i); - if ((node->label != NULL) && (strcmp(node->label, label) == 0)) { - return node; - } - stTree *hit = stTree_findChild(node, label); - if (hit != NULL) { - return hit; - } - } - return NULL; -} - -double stTree_getBranchLength(stTree *tree) { - return tree->branchLength; -} - -void stTree_setBranchLength(stTree *tree, double distance) { - tree->branchLength = distance; -} - -void *stTree_getClientData(stTree *tree) { - return tree->clientData; -} - -void stTree_setClientData(stTree *tree, void *clientData) { - tree->clientData = clientData; -} - - -const char *stTree_getLabel(stTree *tree) { - return tree->label; -} - -void stTree_setLabel(stTree *tree, const char *label) { - if(tree->label != NULL) { - free(tree->label); - } - tree->label = label == NULL ? NULL : stString_copy(label); -} - -int stTree_getNumNodes(stTree *root) { - int cnt = 1; // this node - for (int i = 0; i < stTree_getChildNumber(root); i++) { - cnt += stTree_getNumNodes(stTree_getChild(root, i)); - } - return cnt; -} - -///////////////////////////// -//Newick tree parser -///////////////////////////// - -/* - * Gets the next token from the list. - */ -static void tree_parseNewickTreeString_getNextToken(char **token, char **newickTreeString) { - assert(*token != NULL); - free(*token); - *token = stString_getNextWord(newickTreeString); - assert(*token != NULL); //Newick string must terminate with ';' -} - -/* - * Sets the label, if the token is a label and updates the token. - */ -static void tree_parseNewickString_getLabel(char **token, char **newickTreeString, stTree *tree) { - if(**token != ':' && **token != ',' && **token != ';' && **token != ')') { - stTree_setLabel(tree, *token); - tree_parseNewickTreeString_getNextToken(token, newickTreeString); - } -} - -/* - * Parses any available branch length and updates the token. - */ -static void tree_parseNewickString_getBranchLength(char **token, char **newickTreeString, stTree *tree) { - if (**token == ':') { - tree_parseNewickTreeString_getNextToken(token, newickTreeString); - double distance; - int j = sscanf(*token, "%lf", &distance); - (void)j; - assert(j == 1); - stTree_setBranchLength(tree, distance); - tree_parseNewickTreeString_getNextToken(token, newickTreeString); - } -} - -static stTree *tree_parseNewickStringP(char **token, char **newickTreeString) { - stTree *tree = stTree_construct(); - if((*token)[0] == '(') { - assert(strlen(*token) == 1); - tree_parseNewickTreeString_getNextToken(token, newickTreeString); - while(1) { - stTree_setParent(tree_parseNewickStringP(token, newickTreeString), tree); - assert(strlen(*token) == 1); - if((*token)[0] == ',') { - tree_parseNewickTreeString_getNextToken(token, newickTreeString); - } - else { - break; - } - } - assert((*token)[0] == ')'); //for every opening bracket we must have a close bracket. - tree_parseNewickTreeString_getNextToken(token, newickTreeString); - } - tree_parseNewickString_getLabel(token, newickTreeString, tree); - tree_parseNewickString_getBranchLength(token, newickTreeString, tree); - assert(**token == ',' || **token == ';' || **token == ')'); //these are the correct termination criteria - return tree; -} - -stTree *stTree_parseNewickString(const char *string) { - //lax newick tree parser - char *cA = stString_replace(string, "(", " ( "); - char *cA2 = stString_replace(cA, ")", " ) "); - free(cA); - cA = cA2; - cA2 = stString_replace(cA, ":", " : "); - free(cA); - cA = cA2; - cA2 = stString_replace(cA, ",", " , "); - free(cA); - cA = cA2; - cA2 = stString_replace(cA, ";", " ; "); - free(cA); - cA = cA2; - char *token = stString_getNextWord(&cA); - assert(token != NULL); - stTree *tree = tree_parseNewickStringP(&token, &cA); - assert(*token == ';'); - free(cA2); - free(token); - return tree; -} - -///////////////////////////// -//Newick tree writer -///////////////////////////// - -static char *tree_getNewickTreeStringP(stTree *tree) { - char *cA, *cA2; - if(stTree_getChildNumber(tree) > 0) { - int64_t i; - cA = stString_copy("("); - for(i=0; inodes, sortChildrenListCmpFn); - sortChildrenCmpFn = NULL; - for (int i = 0; i < stTree_getChildNumber(root); i++) { - stTree_sortChildren(stTree_getChild(root, i), cmpFn); - } -} - -void stTree_setChild(stTree *tree, int64_t i, stTree *child) { - assert(i >= 0); - assert(i < stTree_getChildNumber(tree)); - stList_set(tree->nodes, i, child); -} - -stTree *stTree_getMRCA(stTree *node1, stTree *node2) { - // Find all of node 1's parents (inclusive of node 1) - stSet *parents = stSet_construct(); - stTree *curNode = node1; - do { - stSet_insert(parents, curNode); - } while ((curNode = stTree_getParent(curNode)) != NULL); - - // Find the first parent of node 2 that is a parent of node 1 - stTree *ret = NULL; - curNode = node2; - do { - if (stSet_search(parents, curNode) != NULL) { - ret = curNode; - break; - } - } while ((curNode = stTree_getParent(curNode)) != NULL); - - stSet_destruct(parents); - return ret; -} diff --git a/C/impl/sonLibTuples.c b/C/impl/sonLibTuples.c deleted file mode 100644 index 85f1638..0000000 --- a/C/impl/sonLibTuples.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibContainers.c - * - * Created on: 26-May-2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsInternal.h" - -stIntTuple *stIntTuple_construct0() { - stIntTuple *intTuple = st_malloc(sizeof(int64_t) * 1); - intTuple[0] = 0; - return intTuple; -} - -stIntTuple *stIntTuple_construct1(int64_t value) { - stIntTuple *intTuple = st_malloc(sizeof(int64_t) * 2); - intTuple[0] = 1; - intTuple[1] = value; - return intTuple; -} - -stIntTuple *stIntTuple_construct2(int64_t value1, int64_t value2) { - stIntTuple *intTuple = st_malloc(sizeof(int64_t) * 3); - intTuple[0] = 2; - intTuple[1] = value1; - intTuple[2] = value2; - return intTuple; -} - -stIntTuple *stIntTuple_construct3(int64_t value1, int64_t value2, int64_t value3) { - stIntTuple *intTuple = st_malloc(sizeof(int64_t) * 4); - intTuple[0] = 3; - intTuple[1] = value1; - intTuple[2] = value2; - intTuple[3] = value3; - return intTuple; -} - -stIntTuple *stIntTuple_construct4(int64_t value1, int64_t value2, int64_t value3, int64_t value4) { - stIntTuple *intTuple = st_malloc(sizeof(int64_t) * 5); - intTuple[0] = 4; - intTuple[1] = value1; - intTuple[2] = value2; - intTuple[3] = value3; - intTuple[4] = value4; - return intTuple; -} - -stIntTuple *stIntTuple_construct5(int64_t value1, int64_t value2, int64_t value3, int64_t value4, int64_t value5) { - stIntTuple *intTuple = st_malloc(sizeof(int64_t) * 6); - intTuple[0] = 5; - intTuple[1] = value1; - intTuple[2] = value2; - intTuple[3] = value3; - intTuple[4] = value4; - intTuple[5] = value5; - return intTuple; -} - -stIntTuple *stIntTuple_constructN(int64_t length, const int64_t iA[]) { - assert(length >= 0); - stIntTuple *intTuple = st_malloc(sizeof(int64_t) * (length + 1)); - intTuple[0] = length; - for(int64_t i=0; i j ? 1 : 0); -} - -int stIntTuple_cmpFn(stIntTuple *intTuple1, stIntTuple *intTuple2) { - int64_t - i, - j = - stIntTuple_length(intTuple1) < stIntTuple_length(intTuple2) ? stIntTuple_length( - intTuple1) - : stIntTuple_length(intTuple2); - for (i = 0; i < j; i++) { - int64_t k = intCmp(stIntTuple_get(intTuple1, i) - ,stIntTuple_get(intTuple2, i)); - if (k != 0) { - return k; - } - } - return intCmp(stIntTuple_length(intTuple1), stIntTuple_length(intTuple2)); -} - -int stIntTuple_equalsFn(stIntTuple *intTuple1, stIntTuple *intTuple2) { - return stIntTuple_cmpFn(intTuple1, intTuple2) == 0; -} - -int64_t stIntTuple_length(stIntTuple *intTuple) { - return intTuple[0]; -} - -int64_t stIntTuple_get(stIntTuple *intTuple, int64_t index) { - assert(index < stIntTuple_length(intTuple)); - assert(index >= 0); - return intTuple[index + 1]; -} - -/* - * The following are double variants of the above functions. - */ - -stDoubleTuple *stDoubleTuple_construct(int64_t length, ...) { - assert(length >= 0); - stDoubleTuple *doubleTuple = st_malloc(sizeof(double) * (length + 1)); - doubleTuple[0] = length; - int64_t i; - va_list ap; - va_start(ap, length); - for (i = 0; i < length; i++) { - doubleTuple[i + 1] = va_arg(ap, double); - } - va_end(ap); - return doubleTuple; -} - -void stDoubleTuple_destruct(stDoubleTuple *doubleTuple) { - free(doubleTuple); -} - -uint64_t stDoubleTuple_hashKey(stDoubleTuple *doubleTuple) { - int64_t i; - uint64_t j = 0; - - for (i = 0; i < stDoubleTuple_length(doubleTuple); i++) { - //j += stIntTuple_getPosition(intTuple, i); - - // djb2 - // This algorithm was first reported by Dan Bernstein - // many years ago in comp.lang.c - // - j = stDoubleTuple_getPosition(doubleTuple, i) + (j << 6) + (j << 16) - j; - } - return j; -} - -static int doubleCmp(double i, double j) { - return i < j ? -1 : (i > j ? 1 : 0); -} - -int stDoubleTuple_cmpFn(stDoubleTuple *doubleTuple1, - stDoubleTuple *doubleTuple2) { - int64_t i, j = stDoubleTuple_length(doubleTuple1) < stDoubleTuple_length( - doubleTuple2) ? stDoubleTuple_length(doubleTuple1) - : stDoubleTuple_length(doubleTuple2); - for (i = 0; i < j; i++) { - int64_t k = doubleCmp(stDoubleTuple_getPosition(doubleTuple1, i), - stDoubleTuple_getPosition(doubleTuple2, i)); - if (k != 0) { - return k; - } - } - return intCmp(stDoubleTuple_length(doubleTuple1), stDoubleTuple_length( - doubleTuple2)); -} - -int stDoubleTuple_equalsFn(stDoubleTuple *doubleTuple1, - stDoubleTuple *doubleTuple2) { - return stDoubleTuple_cmpFn(doubleTuple1, doubleTuple2) == 0; -} - -int64_t stDoubleTuple_length(stDoubleTuple *doubleTuple) { - return (int64_t) doubleTuple[0]; -} - -double stDoubleTuple_getPosition(stDoubleTuple *doubleTuple, int64_t index) { - assert(index < stDoubleTuple_length(doubleTuple)); - assert(index >= 0); - return doubleTuple[index + 1]; -} - diff --git a/C/impl/stGraph.c b/C/impl/stGraph.c deleted file mode 100644 index d1d5087..0000000 --- a/C/impl/stGraph.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "sonLibGlobalsInternal.h" - -struct _stEdge { - int64_t to; - double weight; - stEdge *nEdge; -}; - -struct _stGraph { - int64_t vertexNo; - stEdge **adjLists; -}; - -stGraph *stGraph_construct(int64_t vertexNo) { - stGraph *graph = st_malloc(sizeof(stGraph)); - graph->vertexNo = vertexNo; - graph->adjLists = st_calloc(vertexNo, sizeof(stEdge *)); - return graph; -} - -void stGraph_destruct(stGraph *g) { - for(int64_t v=0; vvertexNo; v++) { - stEdge *e = g->adjLists[v]; - while(e != NULL) { - stEdge *e2 = e; - e = e->nEdge; - free(e2); - } - } - free(g->adjLists); - free(g); -} - -int64_t stGraph_cardinality(stGraph *g) { - return g->vertexNo; -} - -stEdge *stGraph_getEdges(stGraph *graph, int64_t v) { - return graph->adjLists[v]; -} - -stEdge *stEdge_nextEdge(stEdge *e) { - return e->nEdge; -} - -double stEdge_weight(stEdge *e) { - return e->weight; -} - -int64_t stEdge_to(stEdge *e) { - return e->to; -} - -static void stGraph_addEdgeP(stGraph *graph, int64_t v1, int64_t v2, double weight) { - stEdge *e = st_malloc(sizeof(stEdge)); - e->to = v2; - e->weight = weight; - stEdge *e2 = graph->adjLists[v1]; - graph->adjLists[v1] = e; - e->nEdge = e2; -} - -void stGraph_addEdge(stGraph *graph, int64_t v1, int64_t v2, double weight) { - stGraph_addEdgeP(graph, v1, v2, weight); - stGraph_addEdgeP(graph, v2, v1, weight); -} - -typedef struct _VDistance { - int64_t v; - double distance; -} VDistance; - -int vDistance_cmp(VDistance *vD1, VDistance *vD2) { - return vD1->distance > vD2->distance ? 1 : (vD1->distance < vD2->distance ? -1 : (vD1->v > vD2->v ? 1 : (vD1->v < vD2->v ? -1 : 0))); -} - -double *stGraph_shortestPaths(stGraph *g, int64_t sourceVertex) { - stSortedSet *orderedDistances = stSortedSet_construct3((int (*)(const void *, const void *))vDistance_cmp, NULL); - VDistance *distances = st_malloc(sizeof(VDistance) * stGraph_cardinality(g)); - for(int64_t v=0; vv = v; - vD->distance = (v == sourceVertex ? 0 : INT64_MAX); - stSortedSet_insert(orderedDistances, vD); - } - while(stSortedSet_size(orderedDistances) > 0) { - VDistance *vD = stSortedSet_getFirst(orderedDistances); - stSortedSet_remove(orderedDistances, vD); - stEdge *e = stGraph_getEdges(g, vD->v); - while(e != NULL) { - double d = vD->distance + e->weight; - VDistance *vD2 = &distances[e->to]; - if(vD2->distance > d) { - assert(stSortedSet_search(orderedDistances, vD2) != NULL); - stSortedSet_remove(orderedDistances, vD2); - vD2->distance = d; - stSortedSet_insert(orderedDistances, vD2); - } - e = stEdge_nextEdge(e); - } - } - double *dA = st_malloc(sizeof(double) * stGraph_cardinality(g)); - for(int64_t v=0; vend] = '\0'; - return js + t->start; -} - -int64_t stJson_parseInt(char *js, jsmntok_t *tokens, int64_t tokenIndex) { - jsmntok_t tok = tokens[tokenIndex]; - char *tokStr = stJson_token_tostr(js, &tok); - return atoi(tokStr); -} - -double stJson_parseFloat(char *js, jsmntok_t *tokens, int64_t tokenIndex) { - jsmntok_t tok = tokens[tokenIndex]; - char *tokStr = stJson_token_tostr(js, &tok); - return atof(tokStr); -} - -int64_t stJson_parseFloatArray(double *toArray, int64_t toArraySize, char *js, jsmntok_t *tokens, int64_t tokenIndex) { - jsmntok_t subTok = tokens[tokenIndex]; - if(toArraySize != subTok.size) { - st_errAbort("Reading float array from json but got an unexpected number of tokens. Expected %i but got %i \n", - (int)toArraySize, (int)subTok.size); - } - for (int j = 0; j < subTok.size; j++) { - toArray[j] = stJson_parseFloat(js, tokens, tokenIndex+j+1); - } - return tokenIndex+subTok.size; -} - -bool stJson_parseBool(char *js, jsmntok_t *tokens, int64_t tokenIndex) { - jsmntok_t tok = tokens[tokenIndex]; - char *tokStr = stJson_token_tostr(js, &tok); - assert(strcmp(tokStr, "true") || strcmp(tokStr, "false")); - return strcmp(tokStr, "true") == 0; -} - -int64_t stJson_getNestedTokenCount(jsmntok_t *tokens, int64_t tokenIndex) { - /* - * Gets the number of tokens for the given element and all the nested tokens it contains. - */ - jsmntok_t tok = tokens[tokenIndex]; - int64_t nestedTokens = 1; - for(int64_t i=0; in = n; - matrix->m = m; - matrix->M = st_calloc(n * m, sizeof(double)); - return matrix; -} - -int64_t stMatrix_n(stMatrix *matrix) { - return matrix->n; -} - -int64_t stMatrix_m(stMatrix *matrix) { - return matrix->m; -} - -void stMatrix_destruct(stMatrix *matrix) { - free(matrix->M); - free(matrix); -} - -double *stMatrix_getCell(stMatrix *matrix, int64_t indexN, int64_t indexM) { - assert(indexN >= 0 && indexN < matrix->n); - assert(indexM >= 0 && indexM < matrix->m); - return &(matrix->M[indexN * matrix->m + indexM]); -} - -stMatrix *stMatrix_multiply(stMatrix *matrix1, stMatrix *matrix2) { - if(stMatrix_m(matrix1) != stMatrix_n(matrix2)) { - stThrow(stExcept_new("MATRIX_EXCEPTION", "Matrices do not have equal length dimensions (%" PRIi64 "%" PRIi64 ") to multiply", stMatrix_m(matrix1), stMatrix_n(matrix2))); - } - stMatrix *matrix3 = stMatrix_construct(stMatrix_n(matrix1), stMatrix_m(matrix2)); - for(int64_t i=0; in == matrix2->n); - assert(matrix1->m == matrix2->m); - stMatrix *mergedMatrix = stMatrix_construct(matrix1->n, matrix1->m); - for (int64_t i = 0; i < matrix1->n * matrix1->m; i++) { - mergedMatrix->M[i] = matrix1->M[i] + matrix2->M[i]; - } - return mergedMatrix; -} - -stMatrix *stMatrix_clone(stMatrix *matrix) { - stMatrix *matrix2 = stMatrix_construct(matrix->n, matrix->m); - for (int64_t i = 0; i < matrix->n * matrix->m; i++) { - matrix2->M[i] = matrix->M[i]; - } - return matrix2; -} - -void stMatrix_scale(stMatrix *matrix, double scaleFactor, double addFactor) { - for (int64_t i = 0; i < matrix->n * matrix->m; i++) { - matrix->M[i] = matrix->M[i] * scaleFactor + addFactor; - } -} - -bool stMatrix_equal(stMatrix *matrix1, stMatrix *matrix2, double close) { - if(matrix1->n != matrix2->n || matrix1->m != matrix2->m) { - return 0; - } - for(int64_t i=0; in * matrix1->m; i++) { - if(matrix1->M[i] + close < matrix2->M[i] || matrix1->M[i] - close > matrix2->M[i]) { - return 0; - } - } - return 1; -} - -stMatrix *stMatrix_jukesCantor(double distance, int64_t n) { - stMatrix *jkMatrix = stMatrix_construct(n, n); - for(int64_t i=0; i -#include "sonLib.h" -#include "stPhylogeny.h" -// QuickTree includes -#include "cluster.h" -#include "tree.h" -#include "buildtree.h" -// Spimap C/C++ translation layer include -#include "stSpimapLayer.h" - -// Free stReconciliationInfo properly. -static void stReconciliationInfo_destruct(stReconciliationInfo *info) { - free(info); -} - -static stReconciliationInfo *stReconciliationInfo_clone(stReconciliationInfo *info) { - stReconciliationInfo *ret = st_malloc(sizeof(stReconciliationInfo)); - ret->species = info->species; - ret->event = info->event; - return ret; -} - -static void stIndexedTreeInfo_destruct(stIndexedTreeInfo *info) { - assert(info != NULL); - free(info->leavesBelow); - free(info); -} - -// Free a stPhylogenyInfo struct -void stPhylogenyInfo_destruct(stPhylogenyInfo *info) { - if (info->index != NULL) { - stIndexedTreeInfo_destruct(info->index); - } - if (info->recon != NULL) { - stReconciliationInfo_destruct(info->recon); - } - free(info); -} - -// Clone a stIndexedTreeInfo struct -static stIndexedTreeInfo *stIndexedTreeInfo_clone(stIndexedTreeInfo *info) { - stIndexedTreeInfo *ret = st_malloc(sizeof(stIndexedTreeInfo)); - memcpy(ret, info, sizeof(stIndexedTreeInfo)); - ret->leavesBelow = malloc(ret->totalNumLeaves * sizeof(char)); - memcpy(ret->leavesBelow, info->leavesBelow, ret->totalNumLeaves * sizeof(char)); - return ret; -} - -// Clone a stPhylogenyInfo struct -stPhylogenyInfo *stPhylogenyInfo_clone(stPhylogenyInfo *info) { - stPhylogenyInfo *ret = st_malloc(sizeof(stPhylogenyInfo)); - if (info->index != NULL) { - ret->index = stIndexedTreeInfo_clone(info->index); - } - if (info->recon != NULL) { - ret->recon = stReconciliationInfo_clone(info->recon); - } else { - ret->recon = NULL; - } - return ret; -} - -// Free the stPhylogenyInfo struct for this node and all nodes below it. -void stPhylogenyInfo_destructOnTree(stTree *tree) { - stPhylogenyInfo_destruct(stTree_getClientData(tree)); - stTree_setClientData(tree, NULL); - for (int64_t i = 0; i < stTree_getChildNumber(tree); i++) { - stPhylogenyInfo_destructOnTree(stTree_getChild(tree, i)); - } -} - -// Helper function to add the stIndexedTreeInfo that is normally -// generated during neighbor-joining to a tree that has leaf-labels 0, -// 1, 2, etc. -void addStIndexedTreeInfoR(stTree *tree) -{ - stPhylogenyInfo *info = stTree_getClientData(tree); - if (info == NULL) { - info = st_calloc(1, sizeof(stPhylogenyInfo)); - stTree_setClientData(tree, info); - } - if (info->index != NULL) { - stIndexedTreeInfo_destruct(info->index); - } - stIndexedTreeInfo *indexInfo = st_calloc(1, sizeof(stIndexedTreeInfo)); - info->index = indexInfo; - if(stTree_getChildNumber(tree) == 0) { - int ret; - ret = sscanf(stTree_getLabel(tree), "%" PRIi64, &indexInfo->matrixIndex); - (void) ret; - assert(ret == 1); - } else { - indexInfo->matrixIndex = -1; - for(int64_t i = 0; i < stTree_getChildNumber(tree); i++) { - addStIndexedTreeInfoR(stTree_getChild(tree, i)); - } - } -} - -int64_t stTree_getNumLeaves(stTree *tree) { - int64_t numLeaves = 0; - stList *stack = stList_construct(); - stList_append(stack, tree); - while (stList_length(stack) != 0) { - tree = stList_pop(stack); - for (int64_t i = 0; i < stTree_getChildNumber(tree); i++) { - stList_append(stack, stTree_getChild(tree, i)); - } - if (stTree_getChildNumber(tree) == 0) { - numLeaves++; - } - } - stList_destruct(stack); - return numLeaves; -} - -void stPhylogeny_addStIndexedTreeInfo(stTree *tree) { - addStIndexedTreeInfoR(tree); - stPhylogeny_setLeavesBelow(tree, stTree_getNumLeaves(tree)); -} - - -// Set (and allocate) the leavesBelow and totalNumLeaves attribute in -// the phylogenyInfo for the given tree and all subtrees. The -// phylogenyInfo structure (in the clientData field) must already be -// allocated! -void stPhylogeny_setLeavesBelow(stTree *tree, int64_t totalNumLeaves) -{ - int64_t i, j; - assert(stTree_getClientData(tree) != NULL); - stPhylogenyInfo *info = stTree_getClientData(tree); - assert(info->index != NULL); - stIndexedTreeInfo *indexInfo = info->index; - for (i = 0; i < stTree_getChildNumber(tree); i++) { - stPhylogeny_setLeavesBelow(stTree_getChild(tree, i), totalNumLeaves); - } - - indexInfo->totalNumLeaves = totalNumLeaves; - if (indexInfo->leavesBelow != NULL) { - // leavesBelow has already been allocated somewhere else, free it. - free(indexInfo->leavesBelow); - } - indexInfo->leavesBelow = st_calloc(totalNumLeaves, sizeof(char)); - if (stTree_getChildNumber(tree) == 0) { - assert(indexInfo->matrixIndex < totalNumLeaves); - assert(indexInfo->matrixIndex >= 0); - indexInfo->leavesBelow[indexInfo->matrixIndex] = 1; - } else { - for (i = 0; i < totalNumLeaves; i++) { - for (j = 0; j < stTree_getChildNumber(tree); j++) { - stPhylogenyInfo *childInfo = stTree_getClientData(stTree_getChild(tree, j)); - stIndexedTreeInfo *childIndexInfo = childInfo->index; - indexInfo->leavesBelow[i] |= childIndexInfo->leavesBelow[i]; - } - } - } -} - -static stTree *quickTreeToStTreeR(struct Tnode *tNode) { - stTree *ret = stTree_construct(); - bool hasChild = false; - if (tNode->left != NULL) { - stTree *left = quickTreeToStTreeR(tNode->left); - stTree_setParent(left, ret); - hasChild = true; - } - if (tNode->right != NULL) { - stTree *right = quickTreeToStTreeR(tNode->right); - stTree_setParent(right, ret); - hasChild = true; - } - - // Allocate the phylogenyInfo for this node. - stPhylogenyInfo *info = st_calloc(1, sizeof(stPhylogenyInfo)); - stIndexedTreeInfo *indexInfo = st_calloc(1, sizeof(stIndexedTreeInfo)); - info->index = indexInfo; - if (!hasChild) { - indexInfo->matrixIndex = tNode->nodenumber; - } else { - indexInfo->matrixIndex = -1; - } - stTree_setClientData(ret, info); - - stTree_setBranchLength(ret, tNode->distance); - - // Can remove if needed, probably not useful except for testing. - char *label = stString_print_r("%u", tNode->nodenumber); - stTree_setLabel(ret, label); - free(label); - - return ret; -} - -// Helper function for converting an unrooted QuickTree Tree into an -// stTree. The tree is rooted halfway along the longest branch if -// outgroups is NULL, otherwise it's rooted halfway along the longest -// branch to an outgroup. -static stTree *quickTreeToStTree(struct Tree *tree, stList *outgroups) { - struct Tree *rootedTree = get_root_Tnode(tree); - stTree *ret = quickTreeToStTreeR(rootedTree->child[0]); - stPhylogeny_setLeavesBelow(ret, (stTree_getNumNodes(ret) + 1) / 2); - if(outgroups != NULL && stList_length(outgroups) != 0) { - // Find the longest branch to an outgroup and root the tree - // there. If we're desperate for speedups, we can just root - // the tree once instead of rooting once and then re-rooting. - assert(stList_length(outgroups) != 0); - double maxLength = -1; - stTree *maxNode = NULL; - for(int64_t i = 0; i < stList_length(outgroups); i++) { - int64_t outgroupIndex = stIntTuple_get(stList_get(outgroups, i), 0); - stTree *outgroup = stPhylogeny_getLeafByIndex(ret, outgroupIndex); - if(stTree_getBranchLength(outgroup) > maxLength) { - maxLength = stTree_getBranchLength(outgroup); - maxNode = outgroup; - } - } - assert(maxNode != NULL); - stTree *reRooted = stTree_reRoot(maxNode, maxLength/2); - - // Get rid of the old tree - stPhylogenyInfo_destructOnTree(ret); - stTree_destruct(ret); - - stPhylogeny_addStIndexedTreeInfo(reRooted); - ret = reRooted; - } - free_Tree(tree); - free_Tree(rootedTree); - return ret; -} - -// Compare a single partition to a single bootstrap partition and -// update its support if they are identical. -static void updatePartitionSupportFromPartition(stTree *partitionToScore, - stTree *originalPartition, - stTree *bootstrap) { - stPhylogenyInfo *partitionInfo, *bootstrapInfo; - - partitionInfo = stTree_getClientData(partitionToScore); - bootstrapInfo = stTree_getClientData(bootstrap); - assert(partitionInfo != NULL && partitionInfo->index != NULL); - assert(partitionInfo != NULL && bootstrapInfo->index != NULL); - assert(partitionInfo->index->totalNumLeaves == bootstrapInfo->index->totalNumLeaves); - // Check if the set of leaves is equal in both partitions. If not, - // the partitions can't be equal. - if (memcmp(partitionInfo->index->leavesBelow, bootstrapInfo->index->leavesBelow, - partitionInfo->index->totalNumLeaves * sizeof(char))) { - return; - } - // The partitions are equal, increase the support - partitionInfo->index->numBootstraps++; -} - -// Increase a partition's bootstrap support by supplying the given -// function with the closest possible bootstrap candidate from this -// tree (i.e. it may not be exactly the same branch, if that branch is -// not in the bootstrap). -static void updateSupportFromTree(stTree *partitionToScore, - stTree *originalPartition, - stTree *bootstrapTree, - void (*updateAgainstBootstrapCandidate)(stTree *, stTree *, stTree *)) -{ - stPhylogenyInfo *partitionInfo = stTree_getClientData(partitionToScore); - stPhylogenyInfo *bootstrapInfo = stTree_getClientData(bootstrapTree); - assert(partitionInfo != NULL); - assert(bootstrapInfo != NULL); - stIndexedTreeInfo *partitionIndex = partitionInfo->index; - stIndexedTreeInfo *bootstrapIndex = bootstrapInfo->index; - assert(partitionIndex != NULL); - assert(bootstrapIndex != NULL); - // This partition should be updated against the bootstrap - // partition only if none of the bootstrap's children have a leaf - // set that is a superset of the partition's leaf set. - bool checkThisPartition = TRUE; - - (void) bootstrapIndex; - assert(partitionIndex->totalNumLeaves == bootstrapIndex->totalNumLeaves); - // Check that the leaves under the partition are a subset of the - // leaves under the current bootstrap node. This should always be - // true, since that's checked before running this function - for (int64_t i = 0; i < partitionIndex->totalNumLeaves; i++) { - if (partitionIndex->leavesBelow[i]) { - assert(bootstrapIndex->leavesBelow[i]); - } - } - - for(int64_t i = 0; i < stTree_getChildNumber(bootstrapTree); i++) { - stTree *bootstrapChild = stTree_getChild(bootstrapTree, i); - stPhylogenyInfo *bootstrapChildInfo = stTree_getClientData(bootstrapChild); - assert(bootstrapChildInfo != NULL); - stIndexedTreeInfo *bootstrapChildIndex = bootstrapChildInfo->index; - // If any of the bootstrap's children has a leaf set that is a - // superset of the partition's leaf set, we should update - // against that child instead. - bool isSuperset = TRUE; - for (int64_t j = 0; j < partitionIndex->totalNumLeaves; j++) { - if (partitionIndex->leavesBelow[j]) { - if (!bootstrapChildIndex->leavesBelow[j]) { - isSuperset = FALSE; - break; - } - } - } - if (isSuperset) { - updateSupportFromTree(partitionToScore, originalPartition, - bootstrapChild, - updateAgainstBootstrapCandidate); - checkThisPartition = FALSE; - break; - } - } - - if (checkThisPartition) { - // This bootstrap partition is the closest candidate. Check - // the partition against this node. - updateAgainstBootstrapCandidate(partitionToScore, originalPartition, - bootstrapTree); - } -} - -// Return a new tree which has its partitions scored by how often they -// appear in the bootstrap. This fills in the numBootstraps and -// bootstrapSupport fields of each node. All trees must have valid -// stPhylogenyInfo. -stTree *stPhylogeny_scoreFromBootstrap(stTree *tree, stTree *bootstrap) -{ - stList *list = stList_construct(); - stList_append(list, bootstrap); - stTree *ret = stPhylogeny_scoreFromBootstraps(tree, list); - stList_destruct(list); - return ret; -} - -// Return a new tree which has its partitions scored by how often they -// appear in the bootstraps. This fills in the numBootstraps and -// bootstrapSupport fields of each node. All trees must have valid -// stPhylogenyInfo. -stTree *stPhylogeny_scoreFromBootstraps(stTree *tree, stList *bootstraps) -{ - int64_t i; - stTree *ret = stTree_cloneNode(tree); - stPhylogenyInfo *info = stPhylogenyInfo_clone(stTree_getClientData(tree)); - stTree_setClientData(ret, info); - // Update child partitions (if any) - for(i = 0; i < stTree_getChildNumber(tree); i++) { - stTree_setParent(stPhylogeny_scoreFromBootstraps(stTree_getChild(tree, i), bootstraps), ret); - } - - // Check the current partition against all bootstraps - for(i = 0; i < stList_length(bootstraps); i++) { - updateSupportFromTree(ret, tree, stList_get(bootstraps, i), - updatePartitionSupportFromPartition); - } - - info->index->bootstrapSupport = ((double) info->index->numBootstraps) / stList_length(bootstraps); - return ret; -} - -void updateReconciliationSupportFromPartition(stTree *partitionToScore, - stTree *originalPartition, - stTree *bootstrapPartition) { - stPhylogenyInfo *partitionInfo, *bootstrapInfo; - - // First, check that the branches are identical. - partitionInfo = stTree_getClientData(partitionToScore); - bootstrapInfo = stTree_getClientData(bootstrapPartition); - assert(partitionInfo != NULL); - assert(bootstrapInfo != NULL); - stIndexedTreeInfo *partitionIndex = partitionInfo->index; - stIndexedTreeInfo *bootstrapIndex = bootstrapInfo->index; - assert(partitionIndex != NULL); - assert(bootstrapIndex != NULL); - assert(partitionIndex->totalNumLeaves == bootstrapIndex->totalNumLeaves); - // Check if the set of leaves is equal in both partitions. If not, - // the partitions can't be equal. - if (memcmp(partitionIndex->leavesBelow, bootstrapIndex->leavesBelow, - partitionIndex->totalNumLeaves * sizeof(char))) { - return; - } - - // Now check the reconciliation of the parents. - stTree *partitionParent = stTree_getParent(originalPartition); - stTree *bootstrapParent = stTree_getParent(bootstrapPartition); - if (partitionParent == NULL && bootstrapParent == NULL) { - // We count this case as having identical reconciliation. - partitionIndex->numBootstraps++; - return; - } else if (partitionParent == NULL || bootstrapParent == NULL) { - // If only one is the root, we don't consider them to have the - // same reconciliation. - return; - } - stPhylogenyInfo *partitionParentInfo = stTree_getClientData(partitionParent); - stPhylogenyInfo *bootstrapParentInfo = stTree_getClientData(bootstrapParent); - assert(partitionParentInfo != NULL); - assert(bootstrapParentInfo != NULL); - stReconciliationInfo *partitionParentRecon = partitionParentInfo->recon; - stReconciliationInfo *bootstrapParentRecon = bootstrapParentInfo->recon; - assert(partitionParentRecon != NULL); - assert(bootstrapParentRecon != NULL); - if (partitionParentRecon->event != bootstrapParentRecon->event || - partitionParentRecon->species != bootstrapParentRecon->species) { - // Not the same reconciliation / duplication labeling. - return; - } - // The partitions are equal and they have the same reconciliation, - // increase the support - partitionIndex->numBootstraps++; -} - -stTree *stPhylogeny_scoreReconciliationFromBootstrap(stTree *tree, - stTree *bootstrap) { - stList *list = stList_construct(); - stList_append(list, bootstrap); - stTree *ret = stPhylogeny_scoreReconciliationFromBootstraps(tree, list); - stList_destruct(list); - return ret; -} - -// Return a new tree which has its partitions scored by how often they -// appear with the same reconciliation in the bootstraps. Obviously, -// this is always less than or equal to the normal bootstrap -// score. This fills in the numBootstraps and bootstrapSupport fields -// of each node. All trees must have valid stPhylogenyInfo. -stTree *stPhylogeny_scoreReconciliationFromBootstraps(stTree *tree, - stList *bootstraps) -{ - int64_t i; - stTree *ret = stTree_cloneNode(tree); - stPhylogenyInfo *info = stPhylogenyInfo_clone(stTree_getClientData(tree)); - stTree_setClientData(ret, info); - // Update child partitions (if any) - for(i = 0; i < stTree_getChildNumber(tree); i++) { - stTree_setParent(stPhylogeny_scoreReconciliationFromBootstraps(stTree_getChild(tree, i), bootstraps), ret); - } - // Check the current partition against all bootstraps - for(i = 0; i < stList_length(bootstraps); i++) { - updateSupportFromTree(ret, tree, stList_get(bootstraps, i), - updateReconciliationSupportFromPartition); - } - - info->index->bootstrapSupport = ((double) info->index->numBootstraps) / stList_length(bootstraps); - return ret; -} - -// Only one half of the distanceMatrix is used, distances[i][j] for which i > j -// Tree returned is labeled by the indices of the distance matrix. The -// tree is rooted halfway along the longest branch if outgroups is -// NULL; otherwise, it's rooted halfway along the longest outgroup -// branch. -stTree *stPhylogeny_neighborJoin(stMatrix *distances, stList *outgroups) { - struct DistanceMatrix *distanceMatrix; - struct Tree *tree; - int64_t i, j; - int64_t numSequences = stMatrix_n(distances); - assert(numSequences > 2); - assert(distances != NULL); - assert(stMatrix_n(distances) == stMatrix_m(distances)); - // Set up the basic QuickTree data structures to represent the sequences. - // The data structures are only filled in as much as absolutely - // necessary, so they will probably be invalid for anything but - // running neighbor-joining. - struct ClusterGroup *clusterGroup = empty_ClusterGroup(); - struct Cluster **clusters = st_malloc(numSequences * sizeof(struct Cluster *)); - for (i = 0; i < numSequences; i++) { - struct Sequence *seq = empty_Sequence(); - seq->name = stString_print_r("%" PRIi64, i); - clusters[i] = single_Sequence_Cluster(seq); - } - clusterGroup->clusters = clusters; - clusterGroup->numclusters = numSequences; - // Fill in the QuickTree distance matrix - distanceMatrix = empty_DistanceMatrix(numSequences); - for (i = 0; i < numSequences; i++) { - for (j = 0; j <= i; j++) { - distanceMatrix->data[i][j] = *stMatrix_getCell(distances, i, j); - } - } - clusterGroup->matrix = distanceMatrix; - // Finally, run the neighbor-joining algorithm. - tree = neighbour_joining_buildtree(clusterGroup, 0); - free_ClusterGroup(clusterGroup); - return quickTreeToStTree(tree, outgroups); -} - -// Get the distance to a leaf from an internal node -static double stPhylogeny_distToLeaf(stTree *tree, int64_t leafIndex) { - int64_t i; - stPhylogenyInfo *info = stTree_getClientData(tree); - (void)info; - assert(info->index->leavesBelow[leafIndex]); - if(stTree_getChildNumber(tree) == 0) { - return 0.0; - } - for(i = 0; i < stTree_getChildNumber(tree); i++) { - stTree *child = stTree_getChild(tree, i); - stPhylogenyInfo *childInfo = stTree_getClientData(child); - if(childInfo->index->leavesBelow[leafIndex]) { - return stTree_getBranchLength(child) + stPhylogeny_distToLeaf(child, leafIndex); - } - } - // We shouldn't've gotten here--none of the children have the - // leaf under them, but this node claims to have the leaf under it! - assert(false); - return 0.0/0.0; -} - -// Get the distance to a node from an internal node above it. Will -// fail if the target node is not below. -static double stPhylogeny_distToChild(stTree *tree, stTree *target) { - int64_t i, j; - stPhylogenyInfo *treeInfo, *targetInfo; - treeInfo = stTree_getClientData(tree); - targetInfo = stTree_getClientData(target); - assert(treeInfo != NULL); - assert(targetInfo != NULL); - stIndexedTreeInfo *treeIndex = treeInfo->index; - stIndexedTreeInfo *targetIndex = targetInfo->index; - assert(treeIndex != NULL); - assert(targetIndex != NULL); - assert(treeIndex->totalNumLeaves == targetIndex->totalNumLeaves); - if(memcmp(treeIndex->leavesBelow, targetIndex->leavesBelow, - treeIndex->totalNumLeaves) == 0) { - // This node is the target node - return 0.0; - } - for(i = 0; i < stTree_getChildNumber(tree); i++) { - stTree *child = stTree_getChild(tree, i); - stPhylogenyInfo *childInfo = stTree_getClientData(child); - assert(childInfo != NULL); - stIndexedTreeInfo *childIndex = childInfo->index; - assert(childIndex != NULL); - bool childIsSuperset = true; - // Go through all the children and find one which is above (or - // is) the target node. (Any node above the target will have a - // leaf set that is a superset of the target's leaf set.) - assert(childIndex->totalNumLeaves == treeIndex->totalNumLeaves); - for(j = 0; j < childIndex->totalNumLeaves; j++) { - if(targetIndex->leavesBelow[j] && !childIndex->leavesBelow[j]) { - childIsSuperset = false; - break; - } - } - if(childIsSuperset) { - return stPhylogeny_distToChild(child, target) + stTree_getBranchLength(child); - break; - } - } - // We shouldn't've gotten here--none of the children have the - // target under them, but this node claims to have the target under it! - assert(false); - return 0.0/0.0; -} - - -// Return the MRCA of the given leaves. -stTree *stPhylogeny_getMRCA(stTree *tree, int64_t leaf1, int64_t leaf2) { - for (int64_t i = 0; i < stTree_getChildNumber(tree); i++) { - stTree *child = stTree_getChild(tree, i); - stPhylogenyInfo *childInfo = stTree_getClientData(child); - assert(childInfo != NULL); - stIndexedTreeInfo *childIndex = childInfo->index; - assert(childIndex != NULL); - if(childIndex->leavesBelow[leaf1] && childIndex->leavesBelow[leaf2]) { - return stPhylogeny_getMRCA(child, leaf1, leaf2); - } - } - - // If we've gotten to this point, then this is the MRCA of the leaves. - return tree; -} - -// Find the distance between leaves (given by their index in the -// distance matrix.) -double stPhylogeny_distanceBetweenLeaves(stTree *tree, int64_t leaf1, - int64_t leaf2) { - stTree *mrca = stPhylogeny_getMRCA(tree, leaf1, leaf2); - return stPhylogeny_distToLeaf(mrca, leaf1) + stPhylogeny_distToLeaf(mrca, leaf2); -} - -// Find the distance between two arbitrary nodes (which must be in the -// same tree, with stPhylogenyInfo attached properly). -double stPhylogeny_distanceBetweenNodes(stTree *node1, stTree *node2) { - stPhylogenyInfo *info1, *info2; - if(node1 == node2) { - return 0.0; - } - info1 = stTree_getClientData(node1); - info2 = stTree_getClientData(node2); - stIndexedTreeInfo *index1 = info1->index; - stIndexedTreeInfo *index2 = info2->index; - assert(index1->totalNumLeaves == index2->totalNumLeaves); - // Check if node1 is under node2, vice versa, or if they aren't on - // the same path to the root - bool oneAboveTwo = false, twoAboveOne = false, differentSubsets = true; - for(int64_t i = 0; i < index1->totalNumLeaves; i++) { - if(index1->leavesBelow[i] && index2->leavesBelow[i]) { - differentSubsets = false; - } else if(index2->leavesBelow[i] && !index1->leavesBelow[i]) { - twoAboveOne = true; - // Technically we can break here, but it's cheap to - // double-check that everything is correct. - assert(differentSubsets || oneAboveTwo == false); - } else if(index1->leavesBelow[i] && !index2->leavesBelow[i]) { - oneAboveTwo = true; - assert(differentSubsets || twoAboveOne == false); - } - } - // If differentSubsets is true, then the values of oneAboveTwo and - // twoAboveOne don't matter; if differentSubsets is false, exactly - // one should be true. - (void) twoAboveOne; // stop gcc complaining about this value, - // which is used in asserts - assert(differentSubsets || (oneAboveTwo ^ twoAboveOne)); - - if(differentSubsets) { - stTree *parent = node1; - for(;;) { - parent = stTree_getParent(parent); - assert(parent != NULL); - stPhylogenyInfo *parentInfo = stTree_getClientData(parent); - assert(parentInfo != NULL && parentInfo->index != NULL); - stIndexedTreeInfo *parentIndex = parentInfo->index; - assert(parentIndex->totalNumLeaves == index1->totalNumLeaves); - bool isCommonAncestor = true; - for(int64_t i = 0; i < parentIndex->totalNumLeaves; i++) { - if((index1->leavesBelow[i] || index2->leavesBelow[i]) && - !parentIndex->leavesBelow[i]) { - isCommonAncestor = false; - } - } - if(isCommonAncestor) { - // Found the MRCA of both nodes - break; - } - } - return stPhylogeny_distToChild(parent, node1) + - stPhylogeny_distToChild(parent, node2); - } else if(oneAboveTwo) { - return stPhylogeny_distToChild(node1, node2); - } else { - assert(twoAboveOne); - return stPhylogeny_distToChild(node2, node1); - } -} - -// Gets the (leaf) node corresponding to an index in the distance matrix. -stTree *stPhylogeny_getLeafByIndex(stTree *tree, int64_t leafIndex) { - int64_t i; - stPhylogenyInfo *info = stTree_getClientData(tree); - assert(info != NULL); - stIndexedTreeInfo *index = info->index; - assert(index != NULL); - assert(leafIndex < index->totalNumLeaves); - if(index->matrixIndex == leafIndex) { - return tree; - } - for(i = 0; i < stTree_getChildNumber(tree); i++) { - stTree *child = stTree_getChild(tree, i); - stPhylogenyInfo *childInfo = stTree_getClientData(child); - assert(childInfo != NULL); - stIndexedTreeInfo *childIndex = childInfo->index; - assert(childIndex != NULL); - assert(index->totalNumLeaves == childIndex->totalNumLeaves); - if(childIndex->leavesBelow[leafIndex]) { - return stPhylogeny_getLeafByIndex(child, leafIndex); - } - } - - // Shouldn't get here if the stIndexedTreeInfo is set properly - return NULL; -} - -// Helper function for computeJoinCosts. Populates a map from a tree to a unique int. -static void populateSpeciesToIndex(stTree *speciesTree, stHash *speciesToIndex) { - stList *bfQueue = stList_construct(); - stList_append(bfQueue, speciesTree); - int64_t curIdx = 0; - while (stList_length(bfQueue) != 0) { - stTree *node = stList_pop(bfQueue); - for (int64_t i = 0; i < stTree_getChildNumber(node); i++) { - stList_append(bfQueue, stTree_getChild(node, i)); - } - stHash_insert(speciesToIndex, node, stIntTuple_construct1(curIdx++)); - } - stList_destruct(bfQueue); -} - -// Get the number of nodes between a descendant and its ancestor that -// could cause losses, i.e. that have more than one child. (Exclusive -// of both the ancestor and its descendant, so if the descendant is a -// direct child of the ancestor, that counts as 0.) -static int64_t numSkipsToAncestor(stTree *descendant, stTree *ancestor) { - if (descendant == ancestor) { - return 0; - } - stTree *curNode = descendant; - int64_t ret = 0; - while ((curNode = stTree_getParent(curNode)) != NULL) { - if (curNode == ancestor) { - return ret; - } - if (stTree_getChildNumber(curNode) != 1) { - ret++; - } - } - - // Shouldn't get here. - assert(false); - return -INT64_MAX; -} - -// Get the number of losses in a (left,right)parent; subtree -static int64_t lossesInSubtree(stTree *parent, stTree *left, stTree *right) { - int64_t ret = 0; - ret += numSkipsToAncestor(left, parent) + numSkipsToAncestor(right, parent); - if ((left == parent || right == parent) && (left != right)) { - ret++; - } - return ret; -} - -// Compute join costs for a species tree for use in guided -// neighbor-joining. These costs are calculated by penalizing -// according to the number of dups and losses implied by the -// reconciliation when joining two genes reconciled to certain nodes -// of the species tree. -// speciesToIndex (a blank hash) will be populated with stIntTuples -// corresponding to each species' index into the join cost matrix. -// NB: the species tree must be binary. -// TODO: take branch lengths into account -stMatrix *stPhylogeny_computeJoinCosts(stTree *speciesTree, stHash *speciesToIndex, double costPerDup, double costPerLoss) { - assert(stHash_size(speciesToIndex) == 0); - - int64_t numSpecies = stTree_getNumNodes(speciesTree); - - populateSpeciesToIndex(speciesTree, speciesToIndex); - assert(stHash_size(speciesToIndex) == numSpecies); - - // Fill in the join cost matrix. - stMatrix *ret = stMatrix_construct(numSpecies, numSpecies); - stHash *indexToSpecies = stHash_invert(speciesToIndex, (uint64_t (*)(const void *)) stIntTuple_hashKey, - (int (*)(const void *, const void *)) stIntTuple_equalsFn, NULL, NULL); - for (int64_t i = 0; i < numSpecies; i++) { - // get the species node for this index (the intTuple is - // necessary to query the hash properly) - stIntTuple *query_i = stIntTuple_construct1(i); - stTree *species_i = stHash_search(indexToSpecies, query_i); - assert(species_i != NULL); - for (int64_t j = i; j < numSpecies; j++) { - // get the species node for this index (the intTuple is - // necessary to query the hash properly) - stIntTuple *query_j = stIntTuple_construct1(j); - stTree *species_j = stHash_search(indexToSpecies, query_j); - assert(species_j != NULL); - - // Can't use stPhylogeny_getMRCA as that is only defined for leaves. - stTree *mrca = stTree_getMRCA(species_i, species_j); - - // Calculate the number of dups implied when joining species i and j. - if (species_i == mrca || species_j == mrca) { - // One species is the ancestor of the other, or they - // are equal. This implies one dup. - *stMatrix_getCell(ret, i, j) += costPerDup; - if (j != i) { - *stMatrix_getCell(ret, j, i) += costPerDup; - } - } - - // Calculate the minimum number of losses implied when - // joining species i and j. - int64_t numLosses = lossesInSubtree(mrca, species_i, species_j); - *stMatrix_getCell(ret, i, j) += costPerLoss * numLosses; - if (j != i) { - *stMatrix_getCell(ret, j, i) += costPerLoss * numLosses; - } - - stIntTuple_destruct(query_j); - } - stIntTuple_destruct(query_i); - } - - stHash_destruct(indexToSpecies); - return ret; -} - -int64_t **stPhylogeny_getMRCAMatrix(stTree *speciesTree, stHash *speciesToIndex) { - int64_t numSpecies = stTree_getNumNodes(speciesTree); - int64_t **ret = st_calloc(numSpecies, sizeof(int64_t *)); - for (int64_t i = 0; i < numSpecies; i++) { - ret[i] = st_calloc(numSpecies, sizeof(int64_t)); - } - stHash *indexToSpecies = stHash_invert(speciesToIndex, (uint64_t (*)(const void *)) stIntTuple_hashKey, - (int (*)(const void *, const void *)) stIntTuple_equalsFn, NULL, NULL); - for (int64_t i = 0; i < numSpecies; i++) { - stIntTuple *query_i = stIntTuple_construct1(i); - for (int64_t j = i; j < numSpecies; j++) { - stTree *node_i = stHash_search(indexToSpecies, query_i); - assert(node_i != NULL); - stIntTuple *query_j = stIntTuple_construct1(j); - stTree *node_j = stHash_search(indexToSpecies, query_j); - assert(node_j != NULL); - stTree *mrca = stTree_getMRCA(node_i, node_j); - stIntTuple *mrcaIndex = stHash_search(speciesToIndex, mrca); - assert(mrcaIndex != NULL); - ret[i][j] = stIntTuple_get(mrcaIndex, 0); - ret[j][i] = ret[i][j]; - stIntTuple_destruct(query_j); - } - stIntTuple_destruct(query_i); - } - stHash_destruct(indexToSpecies); - return ret; -} - -stTree *stPhylogeny_guidedNeighborJoining(stMatrix *distanceMatrix, - stMatrix *similarityMatrix, - stMatrix *joinCosts, - stHash *matrixIndexToJoinCostIndex, - stHash *speciesToJoinCostIndex, - int64_t **speciesMRCAMatrix, - stTree *speciesTree) { - int64_t numLeaves = stMatrix_n(similarityMatrix); - assert(numLeaves == stMatrix_m(similarityMatrix)); - assert(numLeaves >= 3); - - // Stores the reconciliation (in join cost matrix indices) for - // each leaf/node. - int64_t *recon = st_calloc(numLeaves, sizeof(int64_t)); - - // Fill in the initial reconciliation array. - stHashIterator *hashIt = stHash_getIterator(matrixIndexToJoinCostIndex); - stIntTuple *matrixIndex; - while ((matrixIndex = stHash_getNext(hashIt)) != NULL) { - int64_t i = stIntTuple_get(matrixIndex, 0); - stIntTuple *joinCostIndex = stHash_search(matrixIndexToJoinCostIndex, matrixIndex); - assert(joinCostIndex != NULL); - recon[i] = stIntTuple_get(joinCostIndex, 0); - } - stHash_destructIterator(hashIt); - - // Distance matrix. We clone the one fed to us since we need to - // modify it during the process. Note: only valid for i < j. - double **distances = st_calloc(numLeaves, sizeof(double *)); - for (int64_t i = 0; i < numLeaves; i++) { - distances[i] = st_calloc(numLeaves, sizeof(double)); - } - - // Confidence matrix (i.e. count of similarities + differences for - // i,j). Note: only valid for i < j. - double **confidences = st_calloc(numLeaves, sizeof(double *)); - for (int64_t i = 0; i < numLeaves; i++) { - confidences[i] = st_calloc(numLeaves, sizeof(double)); - } - - // Fill in our copy of the distance matrix. - for (int64_t i = 0; i < numLeaves; i++) { - for (int64_t j = i + 1; j < numLeaves; j++) { - distances[i][j] = *stMatrix_getCell(distanceMatrix, i, j); - } - } - - // Initial "r" cost (the average of the distances from each node - // to all others) to weight with. - double *r = st_calloc(numLeaves, sizeof(double)); - for (int64_t i = 0; i < numLeaves; i++) { - assert(r[i] == 0.0); - for (int64_t j = 0; j < numLeaves; j++) { - if (i == j) { - continue; - } - if (i < j) { - r[i] += distances[i][j]; - } else { - r[i] += distances[j][i]; - } - } - r[i] /= numLeaves - 2; - } - - // Initialize the join distances (i.e. distance-relative rather - // than the similarity/difference-relative join costs.) Only - // defined for row < col. - double **joinDistances = st_calloc(numLeaves, sizeof(double *)); - for (int64_t i = 0; i < numLeaves; i++) { - joinDistances[i] = st_calloc(numLeaves, sizeof(double)); - for (int64_t j = i + 1; j < numLeaves; j++) { - if (confidences[i][j] != 0) { - joinDistances[i][j] = *stMatrix_getCell(joinCosts, recon[i], recon[j]) / confidences[i][j]; - } else { - // the distance will already be INT64_MAX, just try to - // bias it toward the species tree (although we may - // run into floating-point resolution errors here) - joinDistances[i][j] = *stMatrix_getCell(joinCosts, recon[i], recon[j]); - } - } - } - - // The actual neighbor-joining process. - stTree **nodes = st_calloc(numLeaves, sizeof(stTree *)); - for (int64_t i = 0; i < numLeaves; i++) { - // Initialize nodes. - nodes[i] = stTree_construct(); - char *name = stString_print_r("%" PRIi64, i); - stTree_setLabel(nodes[i], name); - free(name); - } - int64_t numJoinsLeft = numLeaves - 1; - while (numJoinsLeft > 0) { - // Find the lowest distance between any two roots in the - // forest. - double minDist = DBL_MAX; - int64_t mini = -1, minj = -1; - for (int64_t i = 0; i < numLeaves; i++) { - if (recon[i] == -1) { - // Signals that this node has been joined and its - // index is abandoned. - continue; - } - for (int64_t j = i + 1; j < numLeaves; j++) { - if (recon[j] == -1) { - // Signals that this node has been joined and its - // index is abandoned. - continue; - } - double dist = distances[i][j] + joinDistances[i][j] - r[i] - r[j]; - if (dist < minDist) { - mini = i; - minj = j; - minDist = dist; - } - } - } - assert(mini != -1); - assert(minj != -1); - - double dist_mini_minj = distances[mini][minj]; - - // Get the branch lengths for the children of the new node. - double branchLength_mini = (dist_mini_minj + r[mini] - r[minj]) / 2; - double branchLength_minj = dist_mini_minj - branchLength_mini; - // Fix the distances in case of negative branch length. - if ((branchLength_mini <= 0 || branchLength_minj <= 0) && dist_mini_minj < 0) { - branchLength_mini = 0; - branchLength_minj = 0; - } else if (branchLength_mini < 0) { - branchLength_mini = 0; - branchLength_minj = dist_mini_minj; - } else if (branchLength_minj < 0) { - branchLength_mini = dist_mini_minj; - branchLength_minj = 0; - } - - // Join the nodes. - stTree *nodei = nodes[mini]; - assert(nodei != NULL); - stTree *nodej = nodes[minj]; - assert(nodej != NULL); - stTree *joined = stTree_construct(); - stTree_setParent(nodei, joined); - stTree_setParent(nodej, joined); - stTree_setBranchLength(nodei, branchLength_mini); - stTree_setBranchLength(nodej, branchLength_minj); - nodes[mini] = joined; - // Not strictly necessary. - nodes[minj] = NULL; - - // Update the reconciliation of our new joined node to be the - // MRCA of its children's reconciliations. - int64_t recon_i = recon[mini]; - int64_t recon_j = recon[minj]; - recon[mini] = speciesMRCAMatrix[recon_i][recon_j]; - recon[minj] = -1; - - // Update the new row of the distance matrix. - for (int64_t k = 0; k < numLeaves; k++) { - if (recon[k] == -1) { - // Node is gone, don't need to update. - continue; - } - if (k == mini) { - // Skip distance calculation with self - continue; - } - - // calculate the proper indices for accessing i<->k and - // j<->k distances and confidences (the matrix is - // symmetric, so only one half is stored) - int64_t mini_kRow = mini; - int64_t mini_kCol = k; - int64_t minj_kRow = minj; - int64_t minj_kCol = k; - if (mini > k) { - mini_kRow = k; - mini_kCol = mini; - } - if (minj > k) { - minj_kRow = k; - minj_kCol = minj; - } - - confidences[mini_kRow][mini_kCol] = (confidences[mini_kRow][mini_kCol] + confidences[minj_kRow][minj_kCol]) / 2; - - // Update the distances. - double dist_mini_k = distances[mini_kRow][mini_kCol]; - double dist_minj_k = distances[minj_kRow][minj_kCol]; - distances[mini_kRow][mini_kCol] = (dist_mini_k + dist_minj_k - dist_mini_minj) / 2; - - // Update the join distance. - if (confidences[mini_kRow][mini_kCol] != 0) { - joinDistances[mini_kRow][mini_kCol] = *stMatrix_getCell(joinCosts, recon[mini], recon[k]) / confidences[mini_kRow][mini_kCol]; - } else { - joinDistances[mini_kRow][mini_kCol] = *stMatrix_getCell(joinCosts, recon[mini], recon[k]); - } - - // Update r[k]. - if (numJoinsLeft > 2) { - r[k] = ((r[k] * (numJoinsLeft - 1)) - dist_mini_k - dist_minj_k + distances[mini_kRow][mini_kCol]) / (numJoinsLeft - 2); - } else { - r[k] = 0.0; - } - } - - // Set r for the new column. - r[mini] = 0.0; - if (numJoinsLeft > 2) { - for (int64_t k = 0; k < numLeaves; k++) { - if (recon[k] == -1) { - continue; - } - if (k < mini) { - r[mini] += distances[k][mini]; - } else { - r[mini] += distances[mini][k]; - } - } - r[mini] /= numJoinsLeft - 2; - } else { - r[mini] = 0.0; - } - numJoinsLeft--; - } - - stTree *ret = nodes[0]; - assert(ret != NULL); - - // Clean up. - free(recon); - free(r); - free(nodes); - - for (int64_t i = 0; i < numLeaves; i++) { - free(distances[i]); - } - free(distances); - - for (int64_t i = 0; i < numLeaves; i++) { - free(confidences[i]); - } - free(confidences); - - for (int64_t i = 0; i < numLeaves; i++) { - free(joinDistances[i]); - } - free(joinDistances); - - assert(stTree_getNumNodes(ret) == numLeaves * 2 - 1); - - stPhylogeny_addStIndexedTreeInfo(ret); - return ret; -} - -// Fills in stReconciliationInfo, creating the containing -// stPhylogenyInfo if necessary. -static void fillInReconciliationInfo(stTree *gene, stTree *recon, - stReconciliationEvent event, - bool relabelAncestors) { - stPhylogenyInfo *info = stTree_getClientData(gene); - if (info == NULL) { - info = st_calloc(1, sizeof(stPhylogenyInfo)); - stTree_setClientData(gene, info); - } - stReconciliationInfo *reconInfo = info->recon; - if (reconInfo == NULL) { - reconInfo = st_calloc(1, sizeof(stReconciliationInfo)); - info->recon = reconInfo; - } - reconInfo->species = recon; - reconInfo->event = event; - if (stTree_getChildNumber(gene) != 0 && relabelAncestors) { - stTree_setLabel(gene, stTree_getLabel(recon)); - } -} - -static stTree *stPhylogeny_reconcileAtMostBinary_R(stTree *gene, - stHash *leafToSpecies, - bool relabelAncestors) { - stTree *recon; - stReconciliationEvent event; - if (stTree_getChildNumber(gene) == 0) { - // Leaves are already reconciled. - recon = stHash_search(leafToSpecies, gene); - assert(recon != NULL); - event = LEAF; - } else { - event = SPECIATION; - recon = stPhylogeny_reconcileAtMostBinary_R( - stTree_getChild(gene, 0), leafToSpecies, relabelAncestors); - for (int64_t i = 1; i < stTree_getChildNumber(gene); i++) { - stTree *childRecon = stPhylogeny_reconcileAtMostBinary_R( - stTree_getChild(gene, i), leafToSpecies, relabelAncestors); - recon = stTree_getMRCA(childRecon, recon); - } - for (int64_t i = 0; i < stTree_getChildNumber(gene); i++) { - stPhylogenyInfo *childInfo = stTree_getClientData(stTree_getChild(gene, i)); - stTree *childRecon = childInfo->recon->species; - if (childRecon == recon) { - event = DUPLICATION; - } - } - } - fillInReconciliationInfo(gene, recon, event, relabelAncestors); - return recon; -} - -// Reconcile a gene tree (without rerooting), set the proper -// stReconcilationInfo (as an entry of stPhylogenyInfo) as client data -// on all nodes, and optionally set the labels of the ancestors to the -// labels of their reconciliation in the species tree. -// -// The gene tree must be binary, and the species tree must be -// "at-most-binary", i.e. it must have no nodes with more than 3 -// children, but may have nodes with only one child. -void stPhylogeny_reconcileAtMostBinary(stTree *geneTree, stHash *leafToSpecies, - bool relabelAncestors) { - stPhylogeny_reconcileAtMostBinary_R(geneTree, leafToSpecies, - relabelAncestors); -} - -static bool getLinkedSpeciesTree_R(stTree *speciesNode, stTree *polytomy, stHash *speciesToNumGenes, stTree *linkedNode) { - bool hasGene = false; - for (int64_t i = 0; i < stTree_getChildNumber(polytomy); i++) { - stTree *child = stTree_getChild(polytomy, i); - stPhylogenyInfo *childInfo = stTree_getClientData(child); - stReconciliationInfo *childRecon = childInfo->recon; - stTree *childSpecies = childRecon->species; - if (childSpecies == speciesNode) { - hasGene = true; - int64_t *numGenes = stHash_search(speciesToNumGenes, linkedNode); - if (numGenes == NULL) { - numGenes = calloc(1, sizeof(int64_t)); - stHash_insert(speciesToNumGenes, linkedNode, numGenes); - } - (*numGenes)++; - } - } - if (stTree_getChildNumber(speciesNode) == 0 && !hasGene) { - return false; - } - bool descendantHasGene = false; - for (int64_t i = 0; i < stTree_getChildNumber(speciesNode); i++) { - if (getLinkedSpeciesTree_R(stTree_getChild(speciesNode, i), polytomy, - speciesToNumGenes, stTree_getChild(linkedNode, i))) { - descendantHasGene = true; - } - } - - if (!descendantHasGene) { - // have to be careful to always destruct the 0th child here: - // we can't iterate the list of children while destroying the - // children. - int64_t numChildren = stTree_getChildNumber(linkedNode); - for (int64_t i = 0; i < numChildren; i++) { - stTree *linkedChild = stTree_getChild(linkedNode, 0); - stTree_setParent(linkedChild, NULL); - stTree_destruct(linkedChild); - } - } - return descendantHasGene || hasGene; -} - -// Get the "linked species tree" for a polytomy: i.e. the part of the -// species tree corresponding to the polytomy. -stTree *getLinkedSpeciesTree(stTree *speciesTree, stTree *polytomy, stHash **speciesToNumGenes) { - *speciesToNumGenes = stHash_construct2(NULL, free); - stTree *linkedTree = stTree_clone(speciesTree); - getLinkedSpeciesTree_R(speciesTree, polytomy, *speciesToNumGenes, linkedTree); - return linkedTree; -} - -// Calculate the minimum cost for an x-partial resolution of a -// polytomy. -static int64_t minCost(stTree *species, int64_t x, stHash *cupValues) { - stIntTuple *cupParameters = stHash_search(cupValues, species); - assert(cupParameters != NULL); - int64_t m1 = stIntTuple_get(cupParameters, 0); - int64_t m2 = stIntTuple_get(cupParameters, 1); - int64_t gamma = stIntTuple_get(cupParameters, 2); - - if (x < m1) { - return gamma + m1 - x; - } else if (x >= m1 && x <= m2) { - return gamma; - } else { - assert (x > m2); - return gamma + x - m2; - } -} - -static void getCupValues_R(stTree *species, stHash *speciesToNumGenes, stHash *cupValues) { - for (int64_t i = 0; i < stTree_getChildNumber(species); i++) { - getCupValues_R(stTree_getChild(species, i), speciesToNumGenes, cupValues); - } - - int64_t *numGenesPtr = stHash_search(speciesToNumGenes, species); - int64_t numGenes = numGenesPtr ? *numGenesPtr : 0; - int64_t m1, m2, gamma; - if (stTree_getChildNumber(species) == 0) { - if (numGenes == 0) { - m1 = 1; - m2 = 1; - gamma = 1; - } else { - m1 = numGenes; - m2 = numGenes; - gamma = 0; - } - } else { - assert(stTree_getChildNumber(species) == 2); - stTree *child1 = stTree_getChild(species, 0); - stTree *child2 = stTree_getChild(species, 1); - stIntTuple *child1Tuple = stHash_search(cupValues, child1); - stIntTuple *child2Tuple = stHash_search(cupValues, child2); - int64_t child1m1 = stIntTuple_get(child1Tuple, 0); - int64_t child1m2 = stIntTuple_get(child1Tuple, 1); - int64_t child1gamma = stIntTuple_get(child1Tuple, 2); - int64_t child2m1 = stIntTuple_get(child2Tuple, 0); - int64_t child2m2 = stIntTuple_get(child2Tuple, 1); - int64_t child2gamma = stIntTuple_get(child2Tuple, 2); - - if (child1m1 < child2m1 && child1m2 < child2m1) { - m1 = child1m2; - m2 = child2m1; - gamma = child1gamma + child2gamma + child2m1 - child1m2; - } else if (child1m1 < child2m1 && child1m2 >= child2m1 && child1m2 <= child2m2) { - m1 = child2m1; - m2 = child1m2; - gamma = child1gamma + child2gamma; - } else if (child1m1 < child2m1 && child1m2 > child2m2) { - m1 = child2m1; - m2 = child2m2; - gamma = child1gamma + child2gamma; - } else if (child2m1 <= child1m1 && child1m1 <= child2m2 && child2m1 <= child1m2 && child1m2 <= child2m2) { - // The first part of this if condition is duplicated in - // the paper, but it is clear that they mean the case - // where child1's breakpoints are totally enclosed within - // child2's breakpoints. - m1 = child1m1; - m2 = child1m2; - gamma = child1gamma + child2gamma; - } else if (child2m1 <= child1m1 && child1m1 <= child2m2 && child1m2 > child2m2) { - m1 = child1m2; - m2 = child2m2; - gamma = child1gamma + child2gamma; - } else { - m1 = child2m2; - m2 = child1m1; - gamma = child1gamma + child2gamma + child1m1 - child2m2; - } - - m1 = m1 + numGenes; - m2 = m2 + numGenes; - if (m1 <= numGenes) { - m1 = numGenes + 1; - } - if (m2 <= numGenes) { - m2 = numGenes + 1; - gamma = minCost(child1, 1, cupValues) + minCost(child2, 1, cupValues); - } - } - stHash_insert(cupValues, species, stIntTuple_construct3(m1, m2, gamma)); -} - -// Get the "cup values" (i.e. parameters for the minCost function) for -// a polytomy. -static stHash *getCupValues(stTree *speciesTree, stHash *speciesToNumGenes) { - stHash *cupValues = stHash_construct2(NULL, (void (*)(void *)) stIntTuple_destruct); - getCupValues_R(speciesTree, speciesToNumGenes, cupValues); - return cupValues; -} - -// Get the number of duplications and losses in a minimum-cost -// resolution of a polytomy at each node in the species tree. -static void dupLoss(stTree *species, int64_t k, stHash *speciesToNumGenes, stHash *cupValues, stHash *dups, stHash *losses) { - int64_t *numGenesPtr = stHash_search(speciesToNumGenes, species); - int64_t numGenes = numGenesPtr ? *numGenesPtr : 0; - - stIntTuple *cupParameters = stHash_search(cupValues, species); - assert(cupParameters != NULL); - int64_t m1 = stIntTuple_get(cupParameters, 0); - int64_t m2 = stIntTuple_get(cupParameters, 1); - - stTree *child1 = stTree_getChildNumber(species) > 0 ? stTree_getChild(species, 0) : NULL; - stTree *child2 = stTree_getChildNumber(species) > 1 ? stTree_getChild(species, 1) : NULL; - - int64_t *numDups = stHash_search(dups, species); - if (numDups == NULL) { - numDups = st_calloc(1, sizeof(int64_t)); - stHash_insert(dups, species, numDups); - } - int64_t *numLosses = stHash_search(losses, species); - if (numLosses == NULL) { - numLosses = st_calloc(1, sizeof(int64_t)); - stHash_insert(losses, species, numLosses); - } - - if (stTree_getChildNumber(species) == 0) { - if (k >= numGenes) { - *numDups = 0; - *numLosses = k - numGenes; - } else { - *numDups = numGenes - k; - *numLosses = 0; - } - } else if (k - numGenes > 0 && minCost(species, k, cupValues) == minCost(child1, k - numGenes, cupValues) + minCost(child2, k - numGenes, cupValues)) { - *numDups = 0; - *numLosses = 0; - dupLoss(child1, k - numGenes, speciesToNumGenes, cupValues, dups, losses); - dupLoss(child2, k - numGenes, speciesToNumGenes, cupValues, dups, losses); - } else if (k < m1) { - *numDups = m1 - k; - *numLosses = 0; - dupLoss(child1, m1 - numGenes, speciesToNumGenes, cupValues, dups, losses); - dupLoss(child2, m1 - numGenes, speciesToNumGenes, cupValues, dups, losses); - } else if (k > m2) { - *numDups = 0; - *numLosses = k - m2; - dupLoss(child1, m2 - numGenes, speciesToNumGenes, cupValues, dups, losses); - dupLoss(child2, m2 - numGenes, speciesToNumGenes, cupValues, dups, losses); - } -} - -// For a tree that has already been reconciled by -// reconcileAtMostBinary, calculates the number of dups and losses -// implied by the reconciliation. dups and losses must be set to 0 -// before calling. -void stPhylogeny_reconciliationCostAtMostBinary(stTree *reconciledTree, - int64_t *dups, - int64_t *losses) { - stPhylogenyInfo *info = stTree_getClientData(reconciledTree); - assert(info != NULL); - stReconciliationInfo *recon = info->recon; - assert(recon != NULL); - stTree *species = recon->species; - if (stTree_getChildNumber(reconciledTree) == 2) { - if (recon->event == DUPLICATION) { - (*dups)++; - } - // Count losses. - // Look at all this node's children. If the children's recons - // aren't direct children of this node's recon, then count N - // losses, where N is the number of nodes "skipped" on the way to - // this node's recon (plus one if this is a dup and the children's - // recons are not equal). Nodes that have only one child should - // not count as "skipped". - stTree *leftChild = stTree_getChild(reconciledTree, 0); - stPhylogenyInfo *leftInfo = stTree_getClientData(leftChild); - assert(leftInfo != NULL); - stReconciliationInfo *leftRecon = leftInfo->recon; - assert(leftRecon != NULL); - stTree *leftSpecies = leftRecon->species; - - stTree *rightChild = stTree_getChild(reconciledTree, 1); - stPhylogenyInfo *rightInfo = stTree_getClientData(rightChild); - assert(rightInfo != NULL); - stReconciliationInfo *rightRecon = rightInfo->recon; - assert(rightRecon != NULL); - stTree *rightSpecies = rightRecon->species; - - *losses += lossesInSubtree(species, leftSpecies, rightSpecies); - } else if (stTree_getChildNumber(reconciledTree) > 2) { - // We follow the algorithm for finding the minimum mutation - // cost in an apparent polytomy given by Lafond, Swenson, - // El-Mabrouk, 2012. - stHash *speciesToNumGenes; - stTree *linkedSpeciesTree = getLinkedSpeciesTree(species, reconciledTree, &speciesToNumGenes); - stHash *cupValues = getCupValues(linkedSpeciesTree, speciesToNumGenes); - stHash *dupsPerSpecies = stHash_construct2(NULL, free); - stHash *lossesPerSpecies = stHash_construct2(NULL, free); - dupLoss(linkedSpeciesTree, 1, speciesToNumGenes, cupValues, dupsPerSpecies, lossesPerSpecies); - stList *dupValues = stHash_getValues(dupsPerSpecies); - for (int64_t i = 0; i < stList_length(dupValues); i++) { - int64_t *dupsInSpecies = stList_get(dupValues, i); - *dups += *dupsInSpecies; - } - - stList *lossValues = stHash_getValues(lossesPerSpecies); - for (int64_t i = 0; i < stList_length(lossValues); i++) { - int64_t *lossesInSpecies = stList_get(lossValues, i); - *losses += *lossesInSpecies; - } - - stList_destruct(dupValues); - stList_destruct(lossValues); - stHash_destruct(lossesPerSpecies); - stHash_destruct(dupsPerSpecies); - stHash_destruct(cupValues); - stTree_destruct(linkedSpeciesTree); - stHash_destruct(speciesToNumGenes); - } - - for (int64_t i = 0; i < stTree_getChildNumber(reconciledTree); i++) { - stPhylogeny_reconciliationCostAtMostBinary(stTree_getChild(reconciledTree, i), - dups, losses); - } -} - -// Recurse down a tree testing roots to see which would give the -// lowest recon cost if the tree was rooted at that position. -// curRoot is the child of the branch to root on. -void stPhylogeny_rootByReconciliationAtMostBinary_R(stTree *curRoot, - stTree *prevRootParentSpecies, - int64_t prevRootDups, - int64_t prevRootLosses, - int64_t *bestDups, - int64_t *bestLosses, - stTree **bestRoot) { - // The difference between the tree rooted at this branch and the - // one that was rooted previous to this is just the reconciliation - // of the parent of this branch and the new root. So recalculate - // the reconciliation of these nodes, pretending that the tree has - // already been rerooted. - stTree *parent = stTree_getParent(curRoot); - stPhylogenyInfo *parentInfo = stTree_getClientData(parent); - assert(parentInfo != NULL && parentInfo->recon != NULL); - stTree *parentOldSpecies = parentInfo->recon->species; - - // First, the parent of our branch should just be reconciled to - // the MRCA of prev root's parent reconciliation and our sibling's - // reconciliation (which has not changed). - stTree *sibling = NULL; - for (int64_t i = 0; i < stTree_getChildNumber(parent); i++) { - if (stTree_getChild(parent, i) != curRoot) { - sibling = stTree_getChild(parent, i); - } - } - stPhylogenyInfo *siblingInfo = stTree_getClientData(sibling); - assert(siblingInfo != NULL && siblingInfo->recon != NULL); - stTree *siblingSpecies = siblingInfo->recon->species; - // Call this the parent's new species for consistency, although - // now it's the sibling in the new tree. The name is confusing - // either way. - stTree *parentNewSpecies = stTree_getMRCA(prevRootParentSpecies, siblingSpecies); - - // Next, the new root's recon is just the MRCA of our parent's - // recon in the rerooted tree, and the recon of this node (which - // would stay the same). - stPhylogenyInfo *curInfo = stTree_getClientData(curRoot); - assert(curInfo != NULL && curInfo->recon != NULL); - stTree *curSpecies = curInfo->recon->species; - stTree *newRootSpecies = stTree_getMRCA(curSpecies, parentNewSpecies); - - // Find the new cost in dups. This is just (# of old dups) - (old root - // was dup? 1 : 0) - (parent used to be dup? 1 : 0) + (new root is - // dup? 1 : 0) + (parent (now sibling) is now dup? 1 : 0) - int64_t curRootDups = prevRootDups; - if (parentOldSpecies == curSpecies || parentOldSpecies == siblingSpecies) { - curRootDups--; - } - stTree *oldRootSpecies = stTree_getMRCA(prevRootParentSpecies, - parentOldSpecies); - if (oldRootSpecies == prevRootParentSpecies || oldRootSpecies == parentOldSpecies) { - curRootDups--; - } - if (newRootSpecies == curSpecies || newRootSpecies == parentNewSpecies) { - curRootDups++; - } - if (parentNewSpecies == siblingSpecies || parentNewSpecies == prevRootParentSpecies) { - curRootDups++; - } - - // Now find the new cost in losses. - int64_t curRootLosses = prevRootLosses; - curRootLosses -= lossesInSubtree(parentOldSpecies, curSpecies, siblingSpecies); - curRootLosses -= lossesInSubtree(oldRootSpecies, prevRootParentSpecies, parentOldSpecies); - assert(curRootLosses >= 0); - curRootLosses += lossesInSubtree(newRootSpecies, curSpecies, parentNewSpecies); - curRootLosses += lossesInSubtree(parentNewSpecies, siblingSpecies, prevRootParentSpecies); - - if (curRootDups < *bestDups || (curRootDups == *bestDups && curRootLosses < *bestLosses)) { - *bestDups = curRootDups; - *bestLosses = curRootLosses; - *bestRoot = curRoot; - } - for (int64_t i = 0; i < stTree_getChildNumber(curRoot); i++) { - stPhylogeny_rootByReconciliationAtMostBinary_R(stTree_getChild(curRoot, i), - parentNewSpecies, - curRootDups, - curRootLosses, bestDups, - bestLosses, bestRoot); - } -} - -// Return a copy of geneTree that is rooted to minimize duplications, -// with the amount of losses as tiebreaker between roots. -// NOTE: the returned tree does *not* have reconciliation info set, -// and this function will reconcile geneTree, resetting any -// reconciliation information that potentially already exists. -stTree *stPhylogeny_rootByReconciliationAtMostBinary(stTree *geneTree, - stHash *leafToSpecies) { - stPhylogeny_reconcileAtMostBinary(geneTree, leafToSpecies, false); - - // Find the root which has the lowest reconciliation cost. - int64_t dups = 0, losses = 0; - stPhylogeny_reconciliationCostAtMostBinary(geneTree, &dups, &losses); - stTree *bestRoot = geneTree; - int64_t bestDups = dups; - int64_t bestLosses = losses; - if (stTree_getChildNumber(geneTree) == 0) { - return stTree_clone(geneTree); - } else { - assert(stTree_getChildNumber(geneTree) == 2); - stTree *leftChild = stTree_getChild(geneTree, 0); - stTree *rightChild = stTree_getChild(geneTree, 1); - stPhylogenyInfo *leftChildInfo = stTree_getClientData(leftChild); - stTree *leftChildSpecies = leftChildInfo->recon->species; - stPhylogenyInfo *rightChildInfo = stTree_getClientData(rightChild); - stTree *rightChildSpecies = rightChildInfo->recon->species; - for (int64_t i = 0; i < stTree_getChildNumber(leftChild); i++) { - stPhylogeny_rootByReconciliationAtMostBinary_R(stTree_getChild(leftChild, i), - rightChildSpecies, - dups, losses, - &bestDups, - &bestLosses, - &bestRoot); - } - for (int64_t i = 0; i < stTree_getChildNumber(rightChild); i++) { - stPhylogeny_rootByReconciliationAtMostBinary_R(stTree_getChild(rightChild, i), - leftChildSpecies, - dups, losses, - &bestDups, - &bestLosses, - &bestRoot); - } - return stTree_reRoot(bestRoot, stTree_getBranchLength(bestRoot)/2); - } -} - -static void getNewLeafToSpecies_R(stTree *node, stHash *leafToSpecies) { - if (stTree_getChildNumber(node) == 0) { - stPhylogenyInfo *info = stTree_getClientData(node); - assert(info != NULL); - stReconciliationInfo *recon = info->recon; - assert(recon != NULL); - stHash_insert(leafToSpecies, node, recon->species); - } - for (int64_t i = 0; i < stTree_getChildNumber(node); i++) { - getNewLeafToSpecies_R(stTree_getChild(node, i), leafToSpecies); - } - stTree_setClientData(node, NULL); -} - -static stHash *getNewLeafToSpecies(stTree *rerooted) { - stHash *leafToSpecies = stHash_construct(); - getNewLeafToSpecies_R(rerooted, leafToSpecies); - return leafToSpecies; -} - -stTree *stPhylogeny_rootByReconciliationNaive(stTree *tree, stHash *leafToSpecies) { - stPhylogeny_reconcileAtMostBinary(tree, leafToSpecies, false); - stList *stack = stList_construct(); - stList_append(stack, tree); - stTree *bestTree = NULL; - int64_t bestDups = INT64_MAX; - int64_t bestLosses = INT64_MAX; - while (stList_length(stack) > 0) { - stTree *node = stList_pop(stack); - for (int64_t i = 0; i < stTree_getChildNumber(node); i++) { - stList_append(stack, stTree_getChild(node, i)); - } - - stTree *curTree; - if (node != tree) { - curTree = stTree_reRootAndKeepClientData(node, stTree_getBranchLength(node)/2); - } else { - curTree = stTree_clone(tree); - } - stHash *newLeafToSpecies = getNewLeafToSpecies(curTree); - stPhylogeny_reconcileAtMostBinary(curTree, newLeafToSpecies, false); - stHash_destruct(newLeafToSpecies); - int64_t dups = 0, losses = 0; - stPhylogeny_reconciliationCostAtMostBinary(curTree, &dups, &losses); - if (dups < bestDups || (dups == bestDups && losses < bestLosses)) { - if (bestTree != NULL) { - stPhylogenyInfo_destructOnTree(bestTree); - stTree_destruct(bestTree); - } - bestTree = curTree; - bestDups = dups; - bestLosses = losses; - } else { - stPhylogenyInfo_destructOnTree(curTree); - stTree_destruct(curTree); - } - } - stList_destruct(stack); - return bestTree; -} - -static stSet *climb(stTree *childGene, stTree *childLCARecon, stTree *parentGene, - stTree *parentLCARecon, stHash *N) { - stSet *childN = stHash_search(N, childGene); - assert(childN != NULL); - if (stSet_search(childN, parentLCARecon)) { - return childN; - } - - for (int64_t i = 0; i < stTree_getChildNumber(parentLCARecon); i++) { - if (stSet_search(childN, stTree_getChild(parentLCARecon, i))) { - return childN; - } - } - - stSetIterator *setIt = stSet_getIterator(childN); - stTree *x = stSet_getNext(setIt); - stSet_destructIterator(setIt); - - while (stTree_getParent(x) != parentLCARecon) { - x = stTree_getParent(x); - } - - stSet *ret = stSet_construct(); - stSet_insert(ret, x); - stSet_destruct(childN); - return ret; -} - -static stTree *stPhylogeny_reconcileNonBinary_R(stTree *gene, stHash *leafToSpecies, - stHash *N, bool relabelAncestors) { - stTree *LCARecon; - stReconciliationEvent event; - if (stTree_getChildNumber(gene) == 0) { - // Leaves are already reconciled. - LCARecon = stHash_search(leafToSpecies, gene); - assert(LCARecon != NULL); - stSet *myN = stSet_construct(); - stSet_insert(myN, LCARecon); - stHash_insert(N, gene, myN); - event = LEAF; - } else { - // Internal node - // Calculate the LCA mapping - stTree *leftLCARecon = stPhylogeny_reconcileNonBinary_R( - stTree_getChild(gene, 0), leafToSpecies, N, relabelAncestors); - stTree *rightLCARecon = stPhylogeny_reconcileNonBinary_R( - stTree_getChild(gene, 1), leafToSpecies, N, relabelAncestors); - LCARecon = stTree_getMRCA(leftLCARecon, rightLCARecon); - // Calculate if this is a required duplication. We don't - // really care if it's a conditional duplication. - stSet *leftN = climb(stTree_getChild(gene, 0), leftLCARecon, - gene, LCARecon, N); - stSet *rightN = climb(stTree_getChild(gene, 1), rightLCARecon, - gene, LCARecon, N); - stSet *myN = stSet_getUnion(leftN, rightN); - stHash_insert(N, gene, myN); - stSet *intersect = stSet_getIntersection(leftN, rightN); - if (stSet_size(intersect) != 0) { - // This node is a required duplication - event = DUPLICATION; - } else { - // This event is a conditional duplication or a - // speciation. - event = SPECIATION; - } - stSet_destruct(leftN); - stSet_destruct(rightN); - stSet_destruct(intersect); - if (stTree_getParent(gene) == NULL) { - stSet_destruct(myN); - } - } - fillInReconciliationInfo(gene, LCARecon, event, relabelAncestors); - return LCARecon; -} - -void stPhylogeny_reconcileNonBinary(stTree *geneTree, stHash *leafToSpecies, bool relabelAncestors) { - // TODO: this hash is likely unnecessary and values could probably - // be passed up along the tree by stPhylogeny_reconcile_R. - stHash *N = stHash_construct(); - stPhylogeny_reconcileNonBinary_R(geneTree, leafToSpecies, N, relabelAncestors); - stHash_destruct(N); -} - -void stPhylogeny_nni(stTree *anc, stTree **tree1, stTree **tree2) { - if (stTree_getChildNumber(anc) == 0 || stTree_getParent(anc) == NULL) { - // The branch we will be NNI'ing (the branch above anc) isn't - // an internal branch. - *tree1 = NULL; - *tree2 = NULL; - return; - } - - // Get the root of this tree, and a trail of breadcrumbs back to - // the position of this node (child of the branch to be NNI'd). - int64_t distToRoot = 0; - stTree *root = anc; - while (stTree_getParent(root) != NULL) { - root = stTree_getParent(root); - distToRoot++; - } - - bool pathFromRoot[distToRoot]; - int64_t i = distToRoot - 1; - root = anc; - stTree *prev; - while (stTree_getParent(root) != NULL) { - prev = root; - root = stTree_getParent(root); - if (prev == stTree_getChild(root, 0)) { - pathFromRoot[i--] = 0; - } else { - assert(prev == stTree_getChild(root, 1)); - pathFromRoot[i--] = 1; - } - } - - *tree1 = stTree_clone(root); - *tree2 = stTree_clone(root); - - // Traverse down to the right node in tree1 and tree2. - stTree *anc1 = *tree1; - for (i = 0; i < distToRoot; i++) { - if (pathFromRoot[i]) { - anc1 = stTree_getChild(anc1, 1); - } else { - anc1 = stTree_getChild(anc1, 0); - } - } - - stTree *anc2 = *tree2; - for (i = 0; i < distToRoot; i++) { - if (pathFromRoot[i]) { - anc2 = stTree_getChild(anc2, 1); - } else { - anc2 = stTree_getChild(anc2, 0); - } - } - - if (stTree_getParent(stTree_getParent(anc)) != NULL) { - /* - * Not a branch off the root node. - * Original tree: - * \ - * /\ - * 4 /\ - * 3 /\ - * 1 2 - * Tree 1: - * \ - * /\ - * 2 /\ - * 3 /\ - * 1 4 - * Tree 2: - * \ - * /\ - * 4 /\ - * 2 /\ - * 1 3 - */ - // Swap 2 and 4 in tree 1. - stTree *two = stTree_getChild(anc1, 1); - stTree *four; - if (stTree_getChild(stTree_getParent(stTree_getParent(anc1)), 0) == stTree_getParent(anc1)) { - four = stTree_getChild(stTree_getParent(stTree_getParent(anc1)), 1); - } else { - assert(stTree_getChild(stTree_getParent(stTree_getParent(anc1)), 1) == stTree_getParent(anc1)); - four = stTree_getChild(stTree_getParent(stTree_getParent(anc1)), 0); - } - stTree_setParent(two, stTree_getParent(four)); - stTree_setParent(four, anc1); - // Swap 2 and 3 in tree 2. - two = stTree_getChild(anc2, 1); - stTree *three; - if (stTree_getChild(stTree_getParent(anc2), 0) == anc2) { - three = stTree_getChild(stTree_getParent(anc2), 1); - } else { - assert(stTree_getChild(stTree_getParent(anc2), 1) == anc2); - three = stTree_getChild(stTree_getParent(anc2), 0); - } - stTree_setParent(two, stTree_getParent(three)); - stTree_setParent(three, anc2); - } else { - /* - * A branch off the root node. - * Original tree: - * /\ - * / \ - * / \ - * /\ /\ - * 1 2 3 4 - * Tree 1: - * /\ - * / \ - * / \ - * /\ /\ - * 1 4 3 2 - * Tree 2: - * /\ - * / \ - * / \ - * /\ /\ - * 1 3 2 4 - */ - stTree *two = stTree_getChild(anc1, 1); - stTree *three, *four; - if (stTree_getChild(root, 0) == anc) { - three = stTree_getChild(stTree_getChild(*tree2, 1), 0); - four = stTree_getChild(stTree_getChild(*tree1, 1), 1); - } else { - assert(stTree_getChild(root, 1) == anc); - three = stTree_getChild(stTree_getChild(*tree2, 0), 0); - four = stTree_getChild(stTree_getChild(*tree1, 0), 1); - } - // Swap 2 and 4 in tree 1. - stTree_setParent(two, stTree_getParent(four)); - stTree_setParent(four, anc1); - // Swap 2 and 3 in tree 2. - two = stTree_getChild(anc2, 1); - stTree_setParent(two, stTree_getParent(three)); - stTree_setParent(three, anc2); - } -} - -// Determines whether a split satisfies the four-point criterion of -// Bandelt and Dress 1992. The "relaxed" parameter, if true, uses the -// condition stated in the paper (where the intra-split distance must -// not be larger than *both* inter-split distances), but if false, -// uses a stricter condition (that the intra-split distance must be -// smaller than *both* inter-split distances). -static bool satisfiesFourPoint(stMatrix *distanceMatrix, stList *leftSplitIndices, stList *rightSplitIndices, bool relaxed) { - // This is a bit convoluted, but generates all possible - // unordered combinations of indices i, j in the left side of the split. i,j - // are distance matrix indices, not indices in the split list! - for (int64_t left_i = 0; left_i < stList_length(leftSplitIndices); left_i++) { - for (int64_t left_j = left_i + 1; left_j < stList_length(leftSplitIndices); left_j++) { - int64_t i = stIntTuple_get(stList_get(leftSplitIndices, left_i), 0); - int64_t j = stIntTuple_get(stList_get(leftSplitIndices, left_j), 0); - // Similarly, generate all possible unordered combinations - // k, l from the right side of the split. - for (int64_t right_i = 0; right_i < stList_length(rightSplitIndices); right_i++) { - for (int64_t right_j = right_i + 1; right_j < stList_length(rightSplitIndices); right_j++) { - int64_t k = stIntTuple_get(stList_get(rightSplitIndices, right_i), 0); - int64_t l = stIntTuple_get(stList_get(rightSplitIndices, right_j), 0); - // Do the check. - double intra = *stMatrix_getCell(distanceMatrix, i, j) + *stMatrix_getCell(distanceMatrix, k, l); - double inter1 = *stMatrix_getCell(distanceMatrix, i, k) + *stMatrix_getCell(distanceMatrix, j, l); - double inter2 = *stMatrix_getCell(distanceMatrix, i, l) + *stMatrix_getCell(distanceMatrix, j, k); - if (relaxed) { - if (intra >= inter1 && intra >= inter2) { - return false; - } - } else { - if (intra >= inter1 || intra >= inter2) { - return false; - } - } - } - } - } - } - // If we're here, then we've checked all the possible quartets without failing. - return true; -} - -static stSplit *stSplit_construct(stList *leftSplit, stList *rightSplit, double isolationIndex) { - stSplit *ret = st_malloc(sizeof(stSplit)); - ret->leftSplit = leftSplit; - ret->rightSplit = rightSplit; - ret->isolationIndex = isolationIndex; - return ret; -} - -static void stSplit_destruct(stSplit *split) { - stList_destruct(split->leftSplit); - stList_destruct(split->rightSplit); - free(split); -} - -// Compare two d-splits by their isolation indexes. -static int stSplit_cmp(stSplit *split1, stSplit *split2) { - if (split1->isolationIndex < split2->isolationIndex) { - return -1; - } else if (split1->isolationIndex > split2->isolationIndex) { - return 1; - } else { - return 0; - } -} - -static void assignIsolationIndex(stMatrix *distanceMatrix, stSplit *split) { - // We want to find the minimum of (maximum of inter-split distances - intra-split distance) / 2 - // from all cross-split quartets. - double min_isolation = DBL_MAX; - for (int64_t left_i = 0; left_i < stList_length(split->leftSplit); left_i++) { - for (int64_t left_j = left_i + 1; left_j < stList_length(split->leftSplit); left_j++) { - int64_t i = stIntTuple_get(stList_get(split->leftSplit, left_i), 0); - int64_t j = stIntTuple_get(stList_get(split->leftSplit, left_j), 0); - - for (int64_t right_i = 0; right_i < stList_length(split->rightSplit); right_i++) { - for (int64_t right_j = right_i + 1; right_j < stList_length(split->rightSplit); right_j++) { - int64_t k = stIntTuple_get(stList_get(split->rightSplit, right_i), 0); - int64_t l = stIntTuple_get(stList_get(split->rightSplit, right_j), 0); - double intra = *stMatrix_getCell(distanceMatrix, i, j) + *stMatrix_getCell(distanceMatrix, k, l); - double inter1 = *stMatrix_getCell(distanceMatrix, i, k) + *stMatrix_getCell(distanceMatrix, j, l); - double inter2 = *stMatrix_getCell(distanceMatrix, i, l) + *stMatrix_getCell(distanceMatrix, j, k); - double max_dist = intra; - if (inter1 > max_dist) { - max_dist = inter1; - } - if (inter2 > max_dist) { - max_dist = inter2; - } - max_dist -= intra; - if (max_dist < min_isolation) { - min_isolation = max_dist; - } - } - } - } - } - split->isolationIndex = min_isolation / 2; -} - -stList *stPhylogeny_getSplits(stMatrix *distanceMatrix, bool relaxed) { - assert(stMatrix_m(distanceMatrix) == stMatrix_n(distanceMatrix)); - stList *splits = stList_construct3(0, (void (*)(void *)) stSplit_destruct); - for (int64_t i = 1; i < stMatrix_m(distanceMatrix); i++) { - stList *singletonSplitLeft = stList_construct3(0, free); - stList_append(singletonSplitLeft, stIntTuple_construct1(i)); - stList *singletonSplitRight = stList_construct3(0, free); - for (int64_t j = 0; j < i; j++) { - stList_append(singletonSplitRight, stIntTuple_construct1(j)); - } - stList *newSplits = stList_construct3(0, (void (*)(void *)) stSplit_destruct); - stList_append(newSplits, stSplit_construct(singletonSplitLeft, singletonSplitRight, 0.0)); - while (stList_length(splits) > 0) { - stSplit *split = stList_pop(splits); - stIntTuple *iTuple = stIntTuple_construct1(i); - stList_append(split->leftSplit, iTuple); - bool addToLeft = satisfiesFourPoint(distanceMatrix, split->leftSplit, split->rightSplit, relaxed); - stList_pop(split->leftSplit); - stList_append(split->rightSplit, iTuple); - bool addToRight = satisfiesFourPoint(distanceMatrix, split->leftSplit, split->rightSplit, relaxed); - stList_pop(split->rightSplit); - if (addToRight && addToLeft) { - // We are making two new splits, so have to clone the - // lists and their elements. For no particular reason, - // the cloned one becomes the one with i added to the - // right. - - // First we handle the split with i added to its right - // split, cloning the existing list, and add that to - // the new split list. - stList *addedToRight_rightSplit = stList_construct3(0, free); - for (int64_t j = 0; j < stList_length(split->rightSplit); j++) { - stIntTuple *new = stIntTuple_construct1(stIntTuple_get(stList_get(split->rightSplit, j), 0)); - stList_append(addedToRight_rightSplit, new); - } - stList_append(addedToRight_rightSplit, stIntTuple_construct1(i)); - stList *addedToRight_leftSplit = stList_construct3(0, free); - for (int64_t j = 0; j < stList_length(split->leftSplit); j++) { - stIntTuple *new = stIntTuple_construct1(stIntTuple_get(stList_get(split->leftSplit, j), 0)); - stList_append(addedToRight_leftSplit, new); - } - stSplit *addedToRight = stSplit_construct(addedToRight_leftSplit, addedToRight_rightSplit, 0.0); - stList_append(newSplits, addedToRight); - - // Now add i to the left split of the existing split - // and add that to the new split list. - stList_append(split->leftSplit, iTuple); - stList_append(newSplits, split); - } else if (addToRight) { - stList_append(split->rightSplit, iTuple); - stList_append(newSplits, split); - } else if (addToLeft) { - stList_append(split->leftSplit, iTuple); - stList_append(newSplits, split); - } else { - stSplit_destruct(split); - } - } - stList_destruct(splits); - splits = newSplits; - } - - // Remove the remaining trivial splits and assign isolation indexes. - for (int64_t i = 0; i < stList_length(splits); i++) { - stSplit *split = stList_get(splits, i); - assignIsolationIndex(distanceMatrix, split); - if (stList_length(split->leftSplit) == 1 || stList_length(split->rightSplit) == 1) { - // inefficient - stList_remove(splits, i); - stSplit_destruct(split); - // adjusting index to account for removed item - i--; - } - } - - // Sort by isolation index in descending order. - stList_sort(splits, (int (*)(const void *, const void *)) stSplit_cmp); - stList_reverse(splits); - return splits; -} - -static bool isCompatibleSplit(stList *splitIndices, stHash *indexToLeaf) { - stTree *parent = stTree_getParent(stHash_search(indexToLeaf, stList_get(splitIndices, 0))); - assert(parent != NULL); - for (int64_t i = 1; i < stList_length(splitIndices); i++) { - stTree *leaf = stHash_search(indexToLeaf, stList_get(splitIndices, i)); - if (stTree_getParent(leaf) != parent) { - return false; - } - } - return true; -} - -static void applyCompatibleSplit(stList *splitIndices, stHash *indexToLeaf) { - stTree *parent = stTree_getParent(stHash_search(indexToLeaf, stList_get(splitIndices, 0))); - stTree *newNode = stTree_construct(); - stTree_setParent(newNode, parent); - // Branch lengths are arbitrarily set to 1.0. - stTree_setBranchLength(newNode, 1.0); - for (int64_t i = 0; i < stList_length(splitIndices); i++) { - stTree *leaf = stHash_search(indexToLeaf, stList_get(splitIndices, i)); - stTree_setParent(leaf, newNode); - } -} - -stTree *stPhylogeny_greedySplitDecomposition(stMatrix *distanceMatrix, bool relaxed) { - assert(stMatrix_m(distanceMatrix) == stMatrix_n(distanceMatrix)); - stHash *indexToLeaf = stHash_construct3((uint64_t (*)(const void *)) stIntTuple_hashKey, (int (*)(const void *, const void *)) stIntTuple_equalsFn, (void (*)(void *)) stIntTuple_destruct, NULL); - // We start out with a complete star phylogeny. - stTree *root = stTree_construct(); - for (int64_t i = 0; i < stMatrix_m(distanceMatrix); i++) { - stTree *leaf = stTree_construct(); - stHash_insert(indexToLeaf, stIntTuple_construct1(i), leaf); - char *label = stString_print_r("%" PRIi64, i); - stTree_setLabel(leaf, label); - free(label); - stTree_setParent(leaf, root); - // The branch lengths are all arbitrarily set to 1.0 to avoid - // infinite branch lengths setting up a minefield for any - // arithmetic later on. - stTree_setBranchLength(leaf, 1.0); - } - - stList *splits = stPhylogeny_getSplits(distanceMatrix, relaxed); - // Start adding compatible splits to the tree, creating a new - // internal node for each split which groups together one of its - // sides. - for (int64_t i = 0; i < stList_length(splits); i++) { - stSplit *split = stList_get(splits, i); - if (isCompatibleSplit(split->leftSplit, indexToLeaf)) { - applyCompatibleSplit(split->leftSplit, indexToLeaf); - } else if (isCompatibleSplit(split->rightSplit, indexToLeaf)) { - applyCompatibleSplit(split->rightSplit, indexToLeaf); - } - } - stList_destruct(splits); - stHash_destruct(indexToLeaf); - stPhylogeny_addStIndexedTreeInfo(root); - return root; -} - -void stPhylogeny_applyJukesCantorCorrection(stMatrix *distanceMatrix) { - for (int64_t i = 0; i < stMatrix_m(distanceMatrix); i++) { - for (int64_t j = 0; j < stMatrix_n(distanceMatrix); j++) { - if (*stMatrix_getCell(distanceMatrix, i, j) < 0.75) { - *stMatrix_getCell(distanceMatrix, i, j) = -0.75 * log(1 - 4 * (*stMatrix_getCell(distanceMatrix, i, j)) / 3); - } else { - // Having <25% identity isn't valid under the JC - // model, so we just set the distance to something - // higher than any realistic distance (not infinity as - // that may break some arithmetic down the road). - *stMatrix_getCell(distanceMatrix, i, j) = 10000.0; - } - } - } -} diff --git a/C/impl/stPosetAlignment.c b/C/impl/stPosetAlignment.c deleted file mode 100644 index 0654978..0000000 --- a/C/impl/stPosetAlignment.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2009-2011 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "sonLibGlobalsInternal.h" - -struct _stPosetAlignment { - int64_t sequenceNumber; - stSortedSet **constraintLists; -}; - -static int cmpFn(int64_t i, int64_t j) { - return i > j ? 1 : (i < j ? -1 : 0); -} - -static int comparePositions(stIntTuple *position1, stIntTuple *position2) { - if(stIntTuple_get(position1, 0) == INT64_MAX || stIntTuple_get(position2, 0) == INT64_MAX) { //Indicates we should ignore the first position and compare the second. - assert(stIntTuple_get(position1, 1) != INT64_MAX); - assert(stIntTuple_get(position2, 1) != INT64_MAX); - return cmpFn(stIntTuple_get(position1, 1), stIntTuple_get(position2, 1)); - } - return cmpFn(stIntTuple_get(position1, 0), stIntTuple_get(position2, 0)); -} - -stPosetAlignment *stPosetAlignment_construct(int64_t sequenceNumber) { - stPosetAlignment *posetAlignment = st_malloc(sizeof(stPosetAlignment)); - posetAlignment->sequenceNumber = sequenceNumber; - posetAlignment->constraintLists = st_malloc(sizeof(stSortedSet *) * sequenceNumber * sequenceNumber); - for(int64_t i=0; isequenceNumber; i++) { - for(int64_t j=0; jsequenceNumber; j++) { - if(i != j) { - posetAlignment->constraintLists[i*posetAlignment->sequenceNumber + j] = - stSortedSet_construct3((int (*)(const void *, const void *))comparePositions, - (void (*)(void *))stIntTuple_destruct); - } - } - } - return posetAlignment; -} - -void stPosetAlignment_destruct(stPosetAlignment *posetAlignment) { - for(int64_t i=0; isequenceNumber; i++) { - for(int64_t j=0; jsequenceNumber; j++) { - if(i != j) { - stSortedSet_destruct(posetAlignment->constraintLists[i*posetAlignment->sequenceNumber + j]); - } - } - } - free(posetAlignment->constraintLists); - free(posetAlignment); -} - -int64_t stPosetAlignment_getSequenceNumber(stPosetAlignment *posetAlignment) { - return posetAlignment->sequenceNumber; -} - -static stSortedSet *getConstraintList(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t sequence2) { - assert(sequence1 >= 0 && sequence1 < posetAlignment->sequenceNumber); - assert(sequence2 >= 0 && sequence2 < posetAlignment->sequenceNumber); - assert(sequence1 != sequence2); - return posetAlignment->constraintLists[sequence1 * posetAlignment->sequenceNumber + sequence2]; -} - -/* - * Gets the position in sequence2 that the position in sequence2 must be less or equal to in the alignment - */ -static stIntTuple *getConstraint_lessThan(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2) { - stIntTuple *pos = stIntTuple_construct2(position1, INT64_MAX); - //Get less than or equal - stIntTuple *constraint = stSortedSet_searchGreaterThanOrEqual(getConstraintList(posetAlignment, sequence1, sequence2), pos); - stIntTuple_destruct(pos); - assert(constraint == NULL || position1 <= stIntTuple_get(constraint, 0)); - return constraint; -} - -/* - * Gets the position in sequence2 that the position in sequence1 must be greater than or equal to in the alignment - */ -static stIntTuple *getConstraint_greaterThan(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2) { - stIntTuple *pos = stIntTuple_construct2(INT64_MAX, position1); - //Get less than or equal - stIntTuple *constraint = stSortedSet_searchLessThanOrEqual(getConstraintList(posetAlignment, sequence2, sequence1), pos); - stIntTuple_destruct(pos); - assert(constraint == NULL || position1 >= stIntTuple_get(constraint, 1)); - return constraint; -} - -/* - * Returns non-zero iff the constraint is prime. The lessThanOrEquals argument, if non-zero specifies the constraint is less than equals. - */ -static bool lessThanConstraintIsPrime(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2, int64_t position2, int64_t lessThanOrEquals) { - stIntTuple *constraint = getConstraint_lessThan(posetAlignment, sequence1, position1, sequence2); - if(constraint == NULL) { - return 1; - } - if(position2 < stIntTuple_get(constraint, 1)) { //new constraint is tighter - return 1; - } - if(position2 > stIntTuple_get(constraint, 1)) { //new constraint is looser - return 0; - } - if(position1 == stIntTuple_get(constraint, 0) && stIntTuple_get(constraint, 2) && !lessThanOrEquals) { //converts a less than or equals constraint to a less than constraint - return 1; - } - return 0; -} - -/* - * Adds a prime less than (or equals) constraint to the list of prime constraints, removing any redundant constraints in the process. - * The or equals is specified by making the lessThanOrEquals argument non-zero. - */ -void addConstraint_lessThan(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2, int64_t position2, int64_t lessThanOrEquals) { - stSortedSet *constraintList = getConstraintList(posetAlignment, sequence1, sequence2); - assert(position1 != INT64_MAX); - assert(position2 != INT64_MAX); - stIntTuple *constraint1 = stIntTuple_construct3( position1, position2, lessThanOrEquals); - stIntTuple *constraint2; - while((constraint2 = stSortedSet_searchLessThanOrEqual(constraintList, constraint1)) != NULL) { - assert(stIntTuple_get(constraint2, 0) <= position1); - if(stIntTuple_get(constraint2, 1) >= position2) { - if(stIntTuple_get(constraint2, 1) == position2) { //Check we are not removing an equivalent or more severe constraint. - assert((!lessThanOrEquals && stIntTuple_get(constraint2, 2)) || stIntTuple_get(constraint2, 0) < position1); - } - stSortedSet_remove(constraintList, constraint2); - stIntTuple_destruct(constraint2); - } - else { - assert(stIntTuple_get(constraint2, 0) < position1); //Check the constraint does not overshadow our proposed constraint. - break; - } - } - stSortedSet_insert(constraintList, constraint1); -} - -bool stPosetAlignment_isPossibleP(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2, int64_t position2) { - stIntTuple *constraint = getConstraint_lessThan(posetAlignment, sequence1, position1, sequence2); - if(constraint == NULL) { - return 1; - } - if(stIntTuple_get(constraint, 2) && stIntTuple_get(constraint, 0) == position1) { //less than or equals - return position2 <= stIntTuple_get(constraint, 1); - } - else { - return position2 < stIntTuple_get(constraint, 1); - } -} - -bool stPosetAlignment_isPossible(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2, int64_t position2) { - return stPosetAlignment_isPossibleP(posetAlignment, sequence1, position1, sequence2, position2) && - stPosetAlignment_isPossibleP(posetAlignment, sequence2, position2, sequence1, position1); -} - -static void stPosetAlignment_addP2(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t sequence3, int64_t position3, int64_t sequence2, int64_t position2, int64_t lessThanOrEqual) { - for(int64_t sequence4=0; sequence4sequenceNumber; sequence4++) { - if(sequence4 != sequence1 && sequence4 != sequence2 && sequence4 != sequence3) { - stIntTuple *constraint = getConstraint_lessThan(posetAlignment, sequence2, position2, sequence4); - if(constraint != NULL) { - int64_t position4 = stIntTuple_get(constraint, 1); - int64_t transLessThanOrEqual = lessThanOrEqual && stIntTuple_get(constraint, 2) && stIntTuple_get(constraint, 0) == position2; //stuff which maintains the less than or equals - if(lessThanConstraintIsPrime(posetAlignment, sequence3, position3, sequence4, position4, transLessThanOrEqual)) {//We have a new transitive constraint.. - addConstraint_lessThan(posetAlignment, sequence3, position3, sequence4, position4, transLessThanOrEqual); - } - } - } - } -} - -static void stPosetAlignment_addP(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2, int64_t position2) { - //for all pairs do check.. - if(lessThanConstraintIsPrime(posetAlignment, sequence1, position1, sequence2, position2, 1)) { - addConstraint_lessThan(posetAlignment, sequence1, position1, sequence2, position2, 1); - for(int64_t sequence3=0; sequence3sequenceNumber; sequence3++) { - if(sequence3 != sequence2) { - if(sequence3 != sequence1) { - stIntTuple *constraint = getConstraint_greaterThan(posetAlignment, sequence1, position1, sequence3); - if(constraint != NULL) { - int64_t position3 = stIntTuple_get(constraint, 0); //its reversed - int64_t lessThanOrEqual = stIntTuple_get(constraint, 2) && stIntTuple_get(constraint, 1) == position1; - if(lessThanConstraintIsPrime(posetAlignment, sequence3, position3, sequence2, position2, lessThanOrEqual)) { //new constraint found, so add it to the set.. - addConstraint_lessThan(posetAlignment, sequence3, position3, sequence2, position2, lessThanOrEqual); - stPosetAlignment_addP2(posetAlignment, sequence1, sequence3, position3, sequence2, position2, lessThanOrEqual); - } - } - } - else { - stPosetAlignment_addP2(posetAlignment, INT64_MAX, sequence1, position1, sequence2, position2, 1); - } - } - } - } -} - -bool stPosetAlignment_add(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2, int64_t position2) { - if(stPosetAlignment_isPossible(posetAlignment, sequence1, position1, sequence2, position2)) { - stPosetAlignment_addP(posetAlignment, sequence1, position1, sequence2, position2); - stPosetAlignment_addP(posetAlignment, sequence2, position2, sequence1, position1); - return 1; - } - return 0; -} diff --git a/C/impl/stSafeC.c b/C/impl/stSafeC.c deleted file mode 100644 index b704321..0000000 --- a/C/impl/stSafeC.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/** - * Wrappers for C library functions that exit on errors. - */ -#include "stSafeC.h" -#include "sonLibExcept.h" -#include -#include -#include -#include - -const char *ST_SAFEC_NUM_CONVERT_EXCEPTION_ID = "ST_SAFEC_NUM_CONVERT_EXCEPTION_ID"; - -/* Abort function that doesn't allocate any memory */ -void stSafeCErr(const char *msg, ...) { - char buf[256]; - va_list args; - va_start(args, msg); - vsnprintf(buf, sizeof(buf), msg, args); - va_end(args); - // n.b.: check number of bytes here is a hack around not being able - // to turn off gcc -Wunused-result for this special case - int nbytes = write(2, buf, strlen(buf)); - nbytes += write(2, "\n", 1); - _exit(128); -} - -/* Allocate uninitialized memory. */ -void *stSafeCMalloc(size_t size) { - void *mem = malloc(size); - if (mem == NULL) { - stSafeCErr("can't allocate %zd bytes of memory", size); - } - return mem; -} - -/* Allocate zeroed memory. */ -void *stSafeCCalloc(size_t size) { - void *mem = stSafeCMalloc(size); - memset(mem, 0, size); - return mem; -} - -/* Reallocated memory. */ -void *stSafeCRealloc(void *mem, size_t size) { - if ((mem = realloc(mem, size)) == NULL) { - stSafeCErr("can't reallocate %zd bytes of memory", size); - } - return mem; -} - -/* copy a block of memory */ -void *stSafeCCopyMem(void *mem, size_t size) { - void *mem2 = stSafeCMalloc(size); - memcpy(mem2, mem, size); - return mem2; -} - -/* sprintf format with buffer overflow checking. */ -int stSafeCFmtv(char *buffer, int bufSize, const char *format, va_list args) { - int sz = vsnprintf(buffer, bufSize, format, args); - /* note that some version return -1 if too small */ - if ((sz < 0) || (sz >= bufSize)) - stSafeCErr("buffer overflow, size %d, format: %s", bufSize, format); - return sz; -} - -/* sprintf format with buffer overflow checking. */ -int stSafeCFmt(char* buffer, int bufSize, const char *format, ...) { - int sz; - va_list args; - va_start(args, format); - sz = stSafeCFmtv(buffer, bufSize, format, args); - va_end(args); - return sz; -} - -/* sprintf formatting, returning a dynamically allocated string. */ -char *stSafeCDynFmtv(const char *format, va_list args) { - int bufSize = 2*strlen(format); - char *buf = stSafeCMalloc(bufSize); - while (true) { - va_list argscp; - va_copy(argscp, args); - int sz = vsnprintf(buf, bufSize, format, argscp); - va_end(argscp); - - /* note that some version return -1 if too small */ - if ((sz < 0) || (sz >= bufSize)) { - bufSize *= 2; - buf = stSafeCRealloc(buf, bufSize); - } else { - break; - } - } - return buf; -} - -/* sprintf formatting, returning a dynamically allocated string. */ -char *stSafeCDynFmt(const char *format, ...) { - va_list args; - va_start(args, format); - char *buf = stSafeCDynFmtv(format, args); - va_end(args); - return buf; -} - - -/* convert a string to a 32 unsigned int, exception if invalid */ -uint64_t stSafeStrToUInt32(const char *str) { - char *end; - long num = strtol(str, &end, 10); - if ((end == str) || (*end != '\0') || (num < 0)) { - stThrowNew(ST_SAFEC_NUM_CONVERT_EXCEPTION_ID, "invalid 32-bit unsigned integer: \"%s\"", str); - } - return num; -} - -/* convert a string to a 64 int, exception if invalid */ -int64_t stSafeStrToInt64(const char *str) { - char *end; - long long num = strtoll(str, &end, 10); - if ((end == str) || (*end != '\0')) { - stThrowNew(ST_SAFEC_NUM_CONVERT_EXCEPTION_ID, "invalid 64-bit signed integer: \"%s\"", str); - } - return num; -} diff --git a/C/impl/stThreadPool.c b/C/impl/stThreadPool.c deleted file mode 100644 index 89822ee..0000000 --- a/C/impl/stThreadPool.c +++ /dev/null @@ -1,207 +0,0 @@ -// A very simple pthreads thread pool implementation. -// -// A work stack feeds a number of threads. Every work unit is worked -// on by a single thread, which executes the work function, then -// fetches a new work unit when finished. -// -// Often threads only need to write once to some single "result" -// variable, after the heavy computational work is done. To avoid -// needing to manage your own locks for this simple case, an optional -// "finish" function is available, which is guaranteed to run serially -// (although the work function and main thread will still run -// alongside it). If you don't want to use a finishing function, then -// the value returned by the work function is completely ignored. -// -// Note that the work "queue" is actually a stack, not a queue. This -// shouldn't matter, as you have absolutely no ordering guarantees on -// what order the work is completed in regardless. -#include -#include -#include "sonLib.h" - -struct _stThreadPool { - pthread_mutex_t stackLock; // Locks the stack so work can be - // pushed/popped serially. - - pthread_cond_t stackCond; // Signals threads waiting on the - // stack that there's new data. Locked - // by stackLock. - - int64_t numFinishedThreads; // Number of threads currently waiting - // on the stack. Locked by stackLock - // as well. - - pthread_cond_t finishedCond;// Signals the parent thread that work - // just finished. Locked by stackLock. - - stList *stack; // Work units stored here. Locked by - // stackLock. - - pthread_mutex_t finishLock; // Lock to ensure that all "finish" functions - // are done serially. - - pthread_t *threads; // The threads in the pool. - - int64_t numThreads; // Number of threads in the pool. - - void *(*workFunc)(void *); // Function that takes in a work unit - // and returns a result. - - void (*finishFunc)(void *); // Function that takes a result and - // does something with it. - - bool killFlag; // Set when the thread pool wants the - // threads to stop. pthread_cancel - // requires that they hit a - // cancellation point, which isn't - // guaranteed to happen. -}; - -// Worker function for each thread spawned. This function should never -// return until it is cancelled in the destructor. -static void worker(stThreadPool *threadPool) { - int oldtype; - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); - // We don't need the old cancellation type but we have to specify - // a non-NULL argument to be POSIX-compatible - (void) oldtype; - while (1) { - pthread_mutex_lock(&threadPool->stackLock); - // Signal that we're waiting for work. - threadPool->numFinishedThreads++; - while (stList_length(threadPool->stack) == 0 && !threadPool->killFlag) { - // Wake up the main thread in case it's waiting for us to be - // done. - pthread_cond_signal(&threadPool->finishedCond); - // This unlocks the lock and waits to be signaled on stackCond. - pthread_cond_wait(&threadPool->stackCond, &threadPool->stackLock); - // We have the lock again now. - } - - if (threadPool->killFlag) { - // Time to go away now - pthread_mutex_unlock(&threadPool->stackLock); - pthread_exit(NULL); - } - - void *workUnit = stList_pop(threadPool->stack); - // Before unlocking the lock, un-signal that we're waiting for work. - threadPool->numFinishedThreads--; - pthread_mutex_unlock(&threadPool->stackLock); - - // Do the actual work. - void *result = threadPool->workFunc(workUnit); - - // Finish up serially if needed. - if (threadPool->finishFunc != NULL) { - pthread_mutex_lock(&threadPool->finishLock); - threadPool->finishFunc(result); - pthread_mutex_unlock(&threadPool->finishLock); - } - } -} - -// Initialize the thread pool. finishFunc can be NULL if you are -// managing your own locks for output. -stThreadPool *stThreadPool_construct(int64_t numThreads, - void *(*workFunc)(void *), - void (*finishFunc)(void *)) { - assert(numThreads > 0); - stThreadPool *ret = st_calloc(1, sizeof(stThreadPool)); - ret->threads = st_calloc(numThreads, sizeof(pthread_t)); - ret->stack = stList_construct(); - ret->workFunc = workFunc; - ret->finishFunc = finishFunc; - ret->numThreads = numThreads; - - // Set up the locks. - int pthreadError; - pthreadError = pthread_mutex_init(&ret->stackLock, NULL); - if (pthreadError) { - st_errAbort("stThreadPool: pthread_mutex_init failed: %s", - strerror(pthreadError)); - } - pthreadError = pthread_mutex_init(&ret->finishLock, NULL); - if (pthreadError) { - st_errAbort("stThreadPool: pthread_mutex_init failed: %s", - strerror(pthreadError)); - } - pthreadError = pthread_cond_init(&ret->stackCond, NULL); - if (pthreadError) { - st_errAbort("stThreadPool: pthread_cond_init failed: %s", - strerror(pthreadError)); - } - pthreadError = pthread_cond_init(&ret->finishedCond, NULL); - if (pthreadError) { - st_errAbort("stThreadPool: pthread_cond_init failed: %s", - strerror(pthreadError)); - } - - // Start the threads. All initialization of the thread pool struct - // must happen before this, as the threads will look for work - // right away. - for (int64_t i = 0; i < numThreads; i++) { - pthreadError = pthread_create(&ret->threads[i], NULL, - (void *(*)(void *)) worker, ret); - if (pthreadError) { - st_errAbort("stThreadPool: pthread_create failed: %s", - strerror(pthreadError)); - } - } - return ret; -} - -// Push work onto the stack to be consumed by a thread. -void stThreadPool_push(stThreadPool *threadPool, void *workUnit) { - pthread_mutex_lock(&threadPool->stackLock); - stList_append(threadPool->stack, workUnit); - pthread_cond_signal(&threadPool->stackCond); - pthread_mutex_unlock(&threadPool->stackLock); -} - -// Block until all work currently in the stack is complete. Can block -// indefinitely if something goes wrong. Use stThreadPool_waitSafe to -// ensure that you can get execution back after a timeout. -void stThreadPool_wait(stThreadPool *threadPool) { - pthread_mutex_lock(&threadPool->stackLock); - while (stList_length(threadPool->stack) != 0 || threadPool->numFinishedThreads != threadPool->numThreads) { - pthread_cond_wait(&threadPool->finishedCond, &threadPool->stackLock); - } - pthread_mutex_unlock(&threadPool->stackLock); -} - -// Doesn't wait on all the work to complete, just returns whether the -// work in the stack is all done or not. -bool stThreadPool_done(stThreadPool *threadPool) { - pthread_mutex_lock(&threadPool->stackLock); - bool ret = stList_length(threadPool->stack) == 0 && threadPool->numFinishedThreads == threadPool->numThreads; - pthread_mutex_unlock(&threadPool->stackLock); - return ret; -} - -// Destroys the thread pool and destroys all threads. They must finish -// running their work before they exit, but any remaining work in the -// queue will be unfinished. -void stThreadPool_destruct(stThreadPool *threadPool) { - // Wake all currently running threads so they know that they need - // to die. - threadPool->killFlag = true; - for (int64_t i = 0; i < threadPool->numThreads; i++) { - pthread_cond_signal(&threadPool->stackCond); - } - // Ensure that all threads are dead before freeing the memory out - // from under them. - for (int64_t i = 0; i < threadPool->numThreads; i++) { - pthread_join(threadPool->threads[i], NULL); - } - free(threadPool->threads); - - stList_destruct(threadPool->stack); - - pthread_mutex_destroy(&threadPool->stackLock); - pthread_mutex_destroy(&threadPool->finishLock); - pthread_cond_destroy(&threadPool->finishedCond); - pthread_cond_destroy(&threadPool->stackCond); - - free(threadPool); -} diff --git a/C/impl/stUnionFind.c b/C/impl/stUnionFind.c deleted file mode 100644 index f480162..0000000 --- a/C/impl/stUnionFind.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "sonLibGlobalsInternal.h" - -struct _stUnionFind { - stHash *objectToEntry; -}; - -struct _stUnionFindIt { - stList *sets; - int64_t curIndex; -}; - -typedef struct _stUnionFindEntry { - struct _stUnionFindEntry *parent; - void *object; - int64_t rank; -} stUnionFindEntry; - -static void stUnionFindEntry_destruct(stUnionFindEntry *entry) { - free(entry); -} - -stUnionFind *stUnionFind_construct(void) { - stUnionFind *ret = st_malloc(sizeof(stUnionFind)); - ret->objectToEntry = stHash_construct2(NULL, (void (*)(void *)) stUnionFindEntry_destruct); - return ret; -} - -void stUnionFind_destruct(stUnionFind *unionFind) { - stHash_destruct(unionFind->objectToEntry); - free(unionFind); -} - -void stUnionFind_add(stUnionFind *unionFind, void *object) { - stUnionFindEntry *entry = st_malloc(sizeof(stUnionFindEntry)); - entry->object = object; - entry->parent = NULL; - entry->rank = 0; - stHash_insert(unionFind->objectToEntry, object, entry); -} - -void stUnionFind_union(stUnionFind *unionFind, void *object1, void *object2) { - stUnionFindEntry *root1 = stUnionFind_find(unionFind, object1); - stUnionFindEntry *root2 = stUnionFind_find(unionFind, object2); - - assert(root1->parent == NULL && root2->parent == NULL); - - if (root1 == root2) { - return; - } - // keep the tree relatively balanced by checking rank - if (root1->rank > root2->rank) { - root2->parent = root1; - } else if (root1->rank < root2->rank) { - root1->parent = root2; - } else { - root1->parent = root2; - root2->rank++; - } -} - -static stUnionFindEntry *find(stUnionFindEntry *entry) { - // Recursively compress the path to the root by making every node - // visited point directly to the root. - if (entry->parent != NULL) { - entry->parent = find(entry->parent); - } - return entry->parent == NULL ? entry : entry->parent; -} - -void *stUnionFind_find(stUnionFind *unionFind, void *object) { - stUnionFindEntry *entry = stHash_search(unionFind->objectToEntry, object); - assert(entry != NULL); - return find(entry); -} - -stUnionFindIt *stUnionFind_getIterator(stUnionFind *unionFind) { - stHash *rootToSet = stHash_construct(); - stList *entries = stHash_getValues(unionFind->objectToEntry); - for (int64_t i = 0; i < stList_length(entries); i++) { - stUnionFindEntry *entry = stList_get(entries, i); - stUnionFindEntry *root = find(entry); - stSet *set = stHash_search(rootToSet, root); - if (set == NULL) { - set = stSet_construct(); - stHash_insert(rootToSet, root, set); - } - stSet_insert(set, entry->object); - } - stUnionFindIt *it = st_malloc(sizeof(stUnionFindIt)); - it->sets = stHash_getValues(rootToSet); - stList_setDestructor(it->sets, (void (*)(void *)) stSet_destruct); - it->curIndex = 0; - - stList_destruct(entries); - stHash_destruct(rootToSet); - return it; -} - -stSet *stUnionFindIt_getNext(stUnionFindIt *it) { - if (it->curIndex < stList_length(it->sets)) { - return stList_get(it->sets, it->curIndex++); - } else { - return NULL; - } -} - -void stUnionFind_destructIterator(stUnionFindIt *it) { - stList_destruct(it->sets); - free(it); -} diff --git a/C/inc/avl.h b/C/inc/avl.h deleted file mode 100644 index 72b05b1..0000000 --- a/C/inc/avl.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Produced by texiweb from libavl.w. */ - -/* libavl - library for manipulation of binary trees. - Copyright (C) 1998-2002, 2004 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 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. - - The author may be contacted at on the Internet, or - write to Ben Pfaff, Stanford University, Computer Science Dept., 353 - Serra Mall, Stanford CA 94305, USA. -*/ - -#ifndef AVL_H -#define AVL_H 1 - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Function types. */ -typedef int32_t avl_comparison_func (const void *avl_a, const void *avl_b, - void *avl_param); -typedef void avl_item_func (void *avl_item, void *avl_param); -typedef void *avl_copy_func (void *avl_item, void *avl_param); - -#ifndef LIBAVL_ALLOCATOR -#define LIBAVL_ALLOCATOR -/* Memory allocator. */ -struct libavl_allocator - { - void *(*libavl_malloc) (struct libavl_allocator *, size_t libavl_size); - void (*libavl_free) (struct libavl_allocator *, void *libavl_block); - }; -#endif - -/* Default memory allocator. */ -extern struct libavl_allocator avl_allocator_default; -void *avl_malloc (struct libavl_allocator *, size_t); -void avl_free (struct libavl_allocator *, void *); - -/* Maximum AVL height. */ -#ifndef AVL_MAX_HEIGHT -#define AVL_MAX_HEIGHT 64 -#endif - -/* Tree data structure. */ -struct avl_table - { - struct avl_node *avl_root; /* Tree's root. */ - avl_comparison_func *avl_compare; /* Comparison function. */ - void *avl_param; /* Extra argument to |avl_compare|. */ - struct libavl_allocator *avl_alloc; /* Memory allocator. */ - size_t avl_count; /* Number of items in tree. */ - unsigned long avl_generation; /* Generation number. */ - }; - -/* An AVL tree node. */ -struct avl_node - { - struct avl_node *avl_link[2]; /* Subtrees. */ - void *avl_data; /* PoINT_32er to data. */ - signed char avl_balance; /* Balance factor. */ - }; - -/* AVL traverser structure. */ -struct avl_traverser - { - struct avl_table *avl_table; /* Tree being traversed. */ - struct avl_node *avl_node; /* Current node in tree. */ - struct avl_node *avl_stack[AVL_MAX_HEIGHT]; - /* All the nodes above |avl_node|. */ - size_t avl_height; /* Number of nodes in |avl_parent|. */ - unsigned long avl_generation; /* Generation number. */ - }; - -/* Table functions. */ -struct avl_table *avl_create (avl_comparison_func *, void *, - struct libavl_allocator *); -struct avl_table *avl_copy (const struct avl_table *, avl_copy_func *, - avl_item_func *, struct libavl_allocator *); -void avl_destroy (struct avl_table *, avl_item_func *); -void **avl_probe (struct avl_table *, void *); -void *avl_insert (struct avl_table *, void *); -void *avl_replace (struct avl_table *, void *); -void *avl_delete (struct avl_table *, const void *); -void *avl_find (const struct avl_table *, const void *); -void avl_assert_insert (struct avl_table *, void *); -void *avl_assert_delete (struct avl_table *, void *); - -#define avl_count(table) ((size_t) (table)->avl_count) - -/* Table traverser functions. */ -void avl_t_init (struct avl_traverser *, struct avl_table *); -void *avl_t_first (struct avl_traverser *, struct avl_table *); -void *avl_t_last (struct avl_traverser *, struct avl_table *); -void *avl_t_find (struct avl_traverser *, struct avl_table *, void *); -void *avl_find_lessThan(const struct avl_table *tree, const void *item); -void *avl_find_greaterThan(const struct avl_table *tree, const void *item); -void *avl_find_lessThanOrEqual(const struct avl_table *tree, const void *item); -void *avl_find_greaterThanOrEqual(const struct avl_table *tree, const void *item); -void *avl_t_insert (struct avl_traverser *, struct avl_table *, void *); -void *avl_t_copy (struct avl_traverser *, const struct avl_traverser *); -void *avl_t_next (struct avl_traverser *); -void *avl_t_prev (struct avl_traverser *); -void *avl_t_cur (struct avl_traverser *); -void *avl_t_replace (struct avl_traverser *, void *); - -#ifdef __cplusplus -} -#endif -#endif /* avl.h */ diff --git a/C/inc/bioioC.h b/C/inc/bioioC.h deleted file mode 100644 index 0f8884d..0000000 --- a/C/inc/bioioC.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef BIOIOC_H_ -#define BIOIOC_H_ - -#include "commonC.h" - -#ifdef __cplusplus -extern "C" { -#endif - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//integer reader / writer -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -void readIntegers(FILE *file, int64_t intNumber, int64_t *iA); - -void writeIntegers(FILE *file, int64_t intNumber, int64_t *iA); - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//float reader / writer -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -void readDoubles(const char *string, int64_t intNumber, double *dA); - - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//fasta reader/writer -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -char *fastaNormaliseHeader(const char *fastaHeader); - -stList *fastaDecodeHeader(const char *fastaHeader); - -char *fastaEncodeHeader(stList *attributes); - -void fastaRead(FILE *fastaFile, struct List *seqs, struct List *seqLengths, struct List *fastaNames); - -void fastaReadToFunction(FILE *fastaFile, void (*addSeq)(const char *, const char *, int64_t)); - -stHash *fastaReadToMap(FILE *fastaFile); - -void fastaWrite(char *sequence, char *header, FILE *file); - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//read in multi fasta file, and turn into a column alignment -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -struct CharColumnAlignment { - int64_t columnNo; - int64_t seqNo; - char *columnAlignment; -}; - -char *charColumnAlignment_getColumn(struct CharColumnAlignment *charColumnAlignment, int64_t col); - -void destructCharColumnAlignment(struct CharColumnAlignment *charColumnAlignment); - -struct CharColumnAlignment *multiFastaRead(char *fastaFile); - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//newick tree parser -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -struct BinaryTree *newickTreeParser(char *newickTreeString, float defaultDistance, int64_t unaryNodes); - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//useful sscanf functions -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -char *eatWhiteSpace(char *string); - -int64_t parseInt(char **string, int64_t *j); - -int64_t parseFloat(char **string, float *j); - -int64_t parseString(char **string, char *cA); - -/* - * Substitute the string "replacement" for every instance of the character "old" in string "oldString" - * Note: Using the variable replacement instead of new to avoid C++ conflicts - */ -char *replaceString(char *oldString, char old, char *replacement, int64_t newLength); - -/* - * Substitute the string "replacement" for every instance of the character "old" in string "oldString" - * and free oldString. - * Note: Using the variable replacement instead of new to avoid C++ conflicts - */ -char *replaceAndFreeString(char *oldString, char old, char *replacement, int64_t newLength); - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//Get line function, while getline is not in unix. -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -int64_t benLine(char **s, int64_t *n, FILE *f); - -#ifdef __cplusplus -} -#endif -#endif /*BIOIOC_H_*/ diff --git a/C/inc/commonC.h b/C/inc/commonC.h deleted file mode 100644 index fc055ab..0000000 --- a/C/inc/commonC.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef COMMONC_H_ -#define COMMONC_H_ - -#include -#include "fastCMaths.h" -#include "hashTableC.h" -#include "sonLib.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//utils functions - -//logging and debugging -#define DEBUG TRUE - -void exitOnFailure(int64_t exitValue, const char *failureMessage, ...); - -//memory -struct Chunks { - struct List *chunkList; - char * chunk; - //void * chunk; - int64_t remaining; - int64_t chunkSize; - int64_t elementSize; -}; - -struct Chunks *constructChunks(int64_t chunkSize, int64_t elementSize); - -void destructChunks(struct Chunks *); - -void *mallocChunk(struct Chunks *chunk); - - -//general data structures you always need -//lists -struct List { - int64_t length; - int64_t maxLength; - void **list; - void (*destructElement)(void *); -}; - -void listAppend(struct List *list, void *i); - -void *listRemoveFirst(struct List *list); - -void *arrayResize(void *current, int64_t *currentSize, int64_t newSize, int64_t base); - -void listIntersection(struct List *list, struct List *list2, struct List *list3); - -void listResize(struct List *list, int64_t newMaxSize); - -int64_t listGetInt(struct List *list, int64_t index); - -float listGetFloat(struct List *list, int64_t index); - -void listReverse(struct List *list); - -int64_t listContains(struct List *list, void *k); - -void listRemove(struct List *list, void *k); - -void listRemoveDuplicates(struct List *list); - -int64_t listContainsDuplicates(struct List *list); - -void *arrayCopyResize(void *current, int64_t *currentSize, int64_t newSize, int64_t base); - -void *arrayPrepareAppend(void *current, int64_t *maxLength, int64_t currentLength, int64_t base); - -void arrayShuffle(void **array, int64_t n); - -void listCopyResize(struct List *list, int64_t newMaxSize); - -struct List *listCopy(struct List *list); - -void swapListFields(struct List *list1, struct List *list2); - -struct List *cloneList(struct List *source); - -void copyList(struct List *from, struct List *to); - -struct hashtable *intListToHash(struct List *list, int64_t *(*getKey)(void *)); - -//list functions -struct List *copyConstructList(void **list, int64_t length, void (*destructElement)(void *)); - -struct List *constructZeroLengthList(int64_t length, void (*destructElement)(void *)); - -struct List *constructEmptyList(int64_t length, void (*destructElement)(void *)); - -void destructList(struct List *list); - -void listAppendArray(struct List *list, void **array, int64_t length); - -//int lists -struct IntList { - int64_t length; - int64_t maxLength; - int64_t *list; -}; - -struct IntList *constructEmptyIntList(int64_t length); - -void destructIntList(struct IntList *intList); - -struct IntList *intListCopy(struct IntList *intList); - -void intListAppend(struct IntList *intList, int64_t); - -//ints -int64_t *constructInt(int64_t i); - -void destructInt(int64_t *i); - -int64_t *constructChunkInt(int64_t intValue, struct Chunks *chunks); - -int64_t *constructChunkLong(int64_t longValue, struct Chunks *chunks); -//ints -int64_t *constructLong(int64_t i); - -void destructLong(int64_t *i); - -float *constructFloat(float i); - -void destructFloat(float *i); - -uint64_t hashtable_stringHashKey( const void *k ); - -int hashtable_stringEqualKey( const void *key1, const void *key2 ); - -uint64_t hashtable_intHashKey( const void *k ); - -int hashtable_intEqualKey( const void *key1, const void *key2 ); - -uint64_t hashtable_key( const void *k ); - -int hashtable_equalKey( const void *key1, const void *key2 ); - -uint64_t hashtable_intPairHashKey( const void *k ); - -int hashtable_intPairEqualKey( const void *key1, const void *key2 ); - -uint64_t hashtable_orderedIntPairHashKey( const void *k ); - -int hashtable_orderedIntPairEqualKey(const void *key1, const void *key2 ); - -int64_t *constructIntPair(int64_t i, int64_t j); - -void destructIntPair(int64_t *i); - -uint64_t hashtable_longHashKey( const void *k ); - -int hashtable_longEqualKey( const void *key1, const void *key2 ); - -int64_t intComparator(int64_t *i, int64_t *j); - -int64_t longComparator(int64_t *i, int64_t *j); - -int intComparator_Int(int64_t *i, int64_t *j); - -int longComparator_Int(int64_t *i, int64_t *j); - -int64_t intsComparator(int64_t *ints1, int64_t *ints2, int64_t length); - -int floatComparator(float **f, float **f2); - -struct TraversalID { - //tree traversal numbers, used as nodeIDs for identifying - //orders in the tree - //pre == pre order traversal - //preEnd == max pre index + 1 of node in subtree - //mid == mid order (in-order) traversal number - //def __init__(self, pre, preEnd, mid): - int64_t midStart; - int64_t mid; - int64_t midEnd; - int64_t leafNo; -}; - -struct TraversalID *constructTraversalID(int64_t midStart, int64_t mid, int64_t midEnd, int64_t leafNo); - -void destructTraversalID(struct TraversalID *traversalID); - -struct BinaryTree { - float distance; - int64_t internal; - char *label; - struct TraversalID *traversalID; - struct BinaryTree *left; - struct BinaryTree *right; -}; - -int64_t leftMostLeafNo(struct TraversalID *traversalID); - -int64_t rightMostLeafNo(struct TraversalID *traversalID); - -int64_t leafNoInSubtree(struct TraversalID *traversalID); - -struct BinaryTree *constructBinaryTree(float distance, int64_t internal, - const char *label, - struct BinaryTree *left, - struct BinaryTree *right); - -void destructBinaryTree(struct BinaryTree *binaryTree); - -/* - * Gets all the leaf sequences, in depth first, left to right traversal order. - */ -struct List *binaryTree_getOrderedLeafStrings(struct BinaryTree *binaryTree); - -void binaryTree_depthFirstNumbers(struct BinaryTree *binaryTree); - -void printBinaryTree(FILE *file, struct BinaryTree *binaryTree); - -void annotateTree(struct BinaryTree *bT, void *(*fn)(struct BinaryTree *i), struct List *list); - -void getBinaryTreeNodesInMidOrder(struct BinaryTree *binaryTree, struct BinaryTree **labels); - -float linOriginRegression(struct List *pointsX, struct List *pointsY); - -/* - * Joins two paths together, somewhat intelligently, to give one concatenated path. - */ -char *pathJoin(const char *pathPrefix, const char *pathSuffix); - -/* - * Returns non zero if the difference of the two values is within the given precision, - * else returns zero. - */ -int64_t floatValuesClose(double valueOne, double valueTwo, double precision); - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//temp files -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -int64_t constructRandomDir(const char *tempFilePath, char **tempDir); - -int64_t destructRandomDir(char *tempDir); - -void initialiseTempFileTree(char *rootDir, int64_t filesPerDir, int64_t levelNumber); - -char *getTempFile(void); - -void removeTempFile(char *tempFile); - -void removeAllTempFiles(void); - -struct TempFileTree { - char *rootDir; - int64_t filesPerDir; - int64_t *levelsArray; - int64_t levelNumber; - int64_t tempFilesCreated; - int64_t tempFilesDestroyed; -}; - -struct TempFileTree *constructTempFileTree(char *rootDir, int64_t filesPerDir, int64_t levelNumber); - -void destructTempFileTree(struct TempFileTree *tempFileTree); - -char *tempFileTree_getTempFile(struct TempFileTree *tempFileTree); - -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -//graph viz functions -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// - -void graphViz_addNodeToGraph(const char *nodeName, FILE *graphFileHandle, const char *label, - double width, double height, const char *shape, const char *colour, - int64_t fontsize); - -void graphViz_addEdgeToGraph(const char *parentNodeName, const char *childNodeName, FILE *graphFileHandle, - const char *label, const char *colour, double length, double weight, const char *direction); - -void graphViz_setupGraphFile(FILE *graphFileHandle); - -void graphViz_finishGraphFile(FILE *graphFileHandle); - -const char *graphViz_getColour(void); - -#ifdef __cplusplus -} -#endif -#endif /*COMMONC_H_*/ diff --git a/C/inc/fastCMaths.h b/C/inc/fastCMaths.h deleted file mode 100644 index 085643d..0000000 --- a/C/inc/fastCMaths.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/*This code is taken and adapted directly from the probcons library, - * with an addition for random numbers. - */ - -///////////////////////////////////////////////////////////////// -// FLOAT_32.h -// -// Routines for doing math operations in PROBCONS. -///////////////////////////////////////////////////////////////// - -#ifndef FASTCMATHS_H -#define FASTCMATHS_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define TRUE 1 -#define FALSE 0 - -#define LOG_ZERO -INFINITY //-1e300 -//#define LOG_ZERO -1e30000 -//-2e20 -#define LOG_ONE 0.0 -#define ZERO 0.0 -#define ONE 1.0 - -#define INT_STRING "%" PRIi64 - -#define STRING_ARRAY_SIZE 100000 -#define BIG_STRING_ARRAY_SIZE 10000000 - -#define TINY_CHUNK_SIZE 5 -#define SMALL_CHUNK_SIZE 100 -#define MEDIUM_CHUNK_SIZE 1000 -#define LARGE_CHUNK_SIZE 1000000 - -///////////////////////////////////////////////////////////////// -// LOG() -// -// Compute the logarithm of x. -///////////////////////////////////////////////////////////////// - -float LOG (float x); - -///////////////////////////////////////////////////////////////// -// EXP() -// -// Computes exp(x). -///////////////////////////////////////////////////////////////// - -float EXP (float x); - -#define EXP_UNDERFLOW_THRESHOLD -4.6 -#define LOG_UNDERFLOW_THRESHOLD 7.5 - -//const FLOAT_32 EXP_UNDERFLOW_THRESHOLD = -4.6; -//const FLOAT_32 LOG_UNDERFLOW_THRESHOLD = 7.5; - -///////////////////////////////////////////////////////////////// -// LOOKUP() -// -// Computes log (exp (x) + 1), for 0 <= x <= 7.5. -///////////////////////////////////////////////////////////////// - -float LOOKUP (float x); - -///////////////////////////////////////////////////////////////// -// LOG_PLUS_EQUALS() -// -// Add two log probabilities and store in the first argument -///////////////////////////////////////////////////////////////// - -void LOG_PLUS_EQUALS (float *x, float y); - - -///////////////////////////////////////////////////////////////// -// LOG_ADD() -// -// Add two log probabilities -///////////////////////////////////////////////////////////////// - -float LOG_ADD (float x, float y); - - -///////////////////////////////////////////////////////////////// -// LOG_ADD() -// -// Add three log probabilities -///////////////////////////////////////////////////////////////// - -float LOG_ADD_THREE (float x1, float x2, float x3); - -///////////////////////////////////////////////////////////////// -// MAX_EQUALS() -// -// Chooses maximum of two arguments and stores it in the first argument -///////////////////////////////////////////////////////////////// - -void MAX_PLUS_EQUALS (float *x, float y); - -///////////////////////////////////////////////////////////////// -// RANDOM() -// -// Return random FLOAT_32 in range [0 - 1.0 } -///////////////////////////////////////////////////////////////// -float RANDOM(void); - -///////////////////////////////////////////////////////////////// -// RANDOM() -// -// Return random FLOAT_32 in range [0 - 1.0 } -///////////////////////////////////////////////////////////////// -float RANDOM_LOG(void); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/hashTableC.h b/C/inc/hashTableC.h deleted file mode 100644 index f4dcc63..0000000 --- a/C/inc/hashTableC.h +++ /dev/null @@ -1,210 +0,0 @@ -/* Copyright (C) 2002 Christopher Clark */ - -#ifndef __HASHTABLE_CWC22_H__ -#define __HASHTABLE_CWC22_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct hashtable; - -/* Example of use: - * - * struct hashtable *h; - * struct some_key *k; - * struct some_value *v; - * - * static UNSIGNED_INT_32 hash_from_key_fn( void *k ); - * static INT_32 keys_equal_fn ( void *key1, void *key2 ); - * - * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn); - * k = (struct some_key *) malloc(sizeof(struct some_key)); - * v = (struct some_value *) malloc(sizeof(struct some_value)); - * - * (initialise k and v to suitable values) - * - * if (! hashtable_insert(h,k,v) ) - * { exit(-1); } - * - * if (NULL == (found = hashtable_search(h,k) )) - * { printf("not found!"); } - * - * if (NULL == (found = hashtable_remove(h,k) )) - * { printf("Not found\n"); } - * - */ - -/* Macros may be used to define type-safe(r) hashtable access functions, with - * methods specialized to take known key and value types as parameters. - * - * Example: - * - * Insert this at the start of your file: - * - * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value); - * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value); - * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value); - * - * This defines the functions 'insert_some', 'search_some' and 'remove_some'. - * These operate just like hashtable_insert etc., with the same parameters, - * but their function signatures have 'struct some_key *' rather than - * 'void *', and hence can generate compile time errors if your program is - * supplying incorrect data as a key (and similarly for value). - * - * Note that the hash and key equality functions passed to create_hashtable - * still take 'void *' parameters instead of 'some key *'. This shouldn't be - * a difficult issue as they're only defined and passed once, and the other - * functions will ensure that only valid keys are supplied to them. - * - * The cost for this checking is increased code size and runtime overhead - * - if performance is important, it may be worth switching back to the - * unsafe methods once your program has been debugged with the safe methods. - * This just requires switching to some simple alternative defines - eg: - * #define insert_some hashtable_insert - * - */ - -/***************************************************************************** - * create_hashtable - - * @name create_hashtable - * @param minsize minimum initial size of hashtable - * @param hashfunction function for hashing keys - * @param key_eq_fn function for determining key equality - * @return newly created hashtable or NULL on failure - */ - -struct hashtable * -create_hashtable(uint64_t minsize, - uint64_t (*hashfunction) (const void *), - int (*key_eq_fn) (const void*, const void*), - void (*keyFree)(void *), - void (*valueFree)(void *)); - -/***************************************************************************** - * hashtable_insert - - * @name hashtable_insert - * @param h the hashtable to insert INT_32o - * @param k the key - hashtable claims ownership and will free on removal - * @param v the value - does not claim ownership - * @return non-zero for successful insertion - * - * This function will cause the table to expand if the insertion would take - * the ratio of entries to table size over the maximum load factor. - * - * This function does not check for repeated insertions with a duplicate key. - * The value returned when using a duplicate key is undefined -- when - * the hashtable changes size, the order of retrieval of duplicate key - * entries is reversed. - * If in doubt, remove before insert. - */ - -int64_t -hashtable_insert(struct hashtable *h, void *k, void *v); - -#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ -INT_32 fnname (struct hashtable *h, keytype *k, valuetype *v) \ -{ \ - return hashtable_insert(h,k,v); \ -} - -/***************************************************************************** - * hashtable_search - - * @name hashtable_search - * @param h the hashtable to search - * @param k the key to search for - does not claim ownership - * @return the value associated with the key, or NULL if none found - */ - -void * -hashtable_search(struct hashtable *h, void *k); - -#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ -valuetype * fnname (struct hashtable *h, keytype *k) \ -{ \ - return (valuetype *) (hashtable_search(h,k)); \ -} - -/***************************************************************************** - * hashtable_remove - - * @name hashtable_remove - * @param h the hashtable to remove the item from - * @param k the key to search for - does not claim ownership - * @return the value associated with the key, or NULL if none found - */ - -void * /* returns value */ -hashtable_remove(struct hashtable *h, void *k, int64_t freeKey); - -#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ -valuetype * fnname (struct hashtable *h, keytype *k) \ -{ \ - return (valuetype *) (hashtable_remove(h,k)); \ -} - - -/***************************************************************************** - * hashtable_count - - * @name hashtable_count - * @param h the hashtable - * @return the number of items stored in the hashtable - */ -uint64_t -hashtable_count(struct hashtable *h); - - -/***************************************************************************** - * hashtable_destroy - - * @name hashtable_destroy - * @param h the hashtable - * @param free_values whether to call 'free' on the remaining values - */ - -void -hashtable_destroy(struct hashtable *h, int64_t free_values, int64_t free_keys); - -#ifdef __cplusplus -} -#endif -#endif /* __HASHTABLE_CWC22_H__ */ - -/* - * Copyright (c) 2002, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ diff --git a/C/inc/hashTableC_itr.h b/C/inc/hashTableC_itr.h deleted file mode 100644 index f5d587b..0000000 --- a/C/inc/hashTableC_itr.h +++ /dev/null @@ -1,117 +0,0 @@ - -/* Copyright (C) 2002, 2004 Christopher Clark */ - -#ifndef __HASHTABLE_ITR_CWC22__ -#define __HASHTABLE_ITR_CWC22__ - -#include "hashTableC.h" -#include "hashTablePrivateC.h" /* needed to enable inlining */ - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ -/* This struct is only concrete here to allow the inlining of two of the - * accessor functions. */ -struct hashtable_itr -{ - struct hashtable *h; - struct entry *e; - struct entry *parent; - unsigned int index; -}; - - -/*****************************************************************************/ -/* hashtable_iterator - */ - -struct hashtable_itr * -hashtable_iterator(struct hashtable *h); - -/*****************************************************************************/ -/* hashtable_iterator_key - * - return the value of the (key,value) pair at the current position */ - -static inline void * -hashtable_iterator_key(struct hashtable_itr *i) -{ return i->e->k; } - -/*****************************************************************************/ -/* value - return the value of the (key,value) pair at the current position */ - -static inline void * -hashtable_iterator_value(struct hashtable_itr *i) -{ return i->e->v; } - -/*****************************************************************************/ -/* advance - advance the iterator to the next element - * returns zero if advanced to end of table */ - -int -hashtable_iterator_advance(struct hashtable_itr *itr); - -/*****************************************************************************/ -/* remove - remove current element and advance the iterator to the next element - * NB: if you need the value to free it, read it before - * removing. ie: beware memory leaks! - * returns zero if advanced to end of table */ - -int -hashtable_iterator_remove(struct hashtable_itr *itr); - -/*****************************************************************************/ -/* search - overwrite the supplied iterator, to point to the entry - * matching the supplied key. - h points to the hashtable to be searched. - * returns zero if not found. */ -int -hashtable_iterator_search(struct hashtable_itr *itr, - struct hashtable *h, void *k); - -#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \ -int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \ -{ \ - return (hashtable_iterator_search(i,h,k)); \ -} - - - -#ifdef __cplusplus -} -#endif -#endif /* __HASHTABLE_ITR_CWC22__*/ - -/* - * Copyright (c) 2002, 2004, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ diff --git a/C/inc/hashTablePrivateC.h b/C/inc/hashTablePrivateC.h deleted file mode 100644 index cce7597..0000000 --- a/C/inc/hashTablePrivateC.h +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2002, 2004 Christopher Clark */ - -#ifndef __HASHTABLE_PRIVATE_CWC22_H__ -#define __HASHTABLE_PRIVATE_CWC22_H__ - -#include "hashTableC.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ - -struct entry -{ - void *k, *v; - uint64_t h; - struct entry *next; -}; - -struct hashtable { - uint64_t tablelength; - struct entry **table; - uint64_t entrycount; - uint64_t loadlimit; - uint64_t primeindex; - uint64_t (*hashfn) (const void *k); - int (*eqfn) (const void *k1, const void *k2); - void (*keyFree)(void *); - void (*valueFree)(void *); -}; - -/*****************************************************************************/ -uint64_t -hashP(struct hashtable *h, void *k); - -/*****************************************************************************/ -/* indexFor -static uint64_t -indexFor(uint64_t tablelength, uint64_t hashvalue) { - return (hashvalue % tablelength); -}*/ - -/* Only works if tablelength == 2^N */ -/*static UNSIGNED_INT_32 -indexFor(UNSIGNED_INT_32 tablelength, UNSIGNED_INT_32 hashvalue) -{ - return (hashvalue & (tablelength - 1u)); -} -*/ - -/*****************************************************************************/ -#define freekey(X) free(X) /* this is used by hashTableC_itr */ -/*define freekey(X) ; */ - - -/*****************************************************************************/ - -#ifdef __cplusplus -} -#endif -#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/ - -/* - * Copyright (c) 2002, Christopher Clark - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ diff --git a/C/inc/jsmn.h b/C/inc/jsmn.h deleted file mode 100644 index 9234d19..0000000 --- a/C/inc/jsmn.h +++ /dev/null @@ -1,98 +0,0 @@ -/*Copyright (c) 2010 Serge A. Zaitsev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE.*/ - - - -#ifndef __JSMN_H_ -#define __JSMN_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * JSON type identifier. Basic types are: - * o Object - * o Array - * o String - * o Other primitive: number, boolean (true/false) or null - */ -typedef enum { - JSMN_UNDEFINED = 0, - JSMN_OBJECT = 1, - JSMN_ARRAY = 2, - JSMN_STRING = 3, - JSMN_PRIMITIVE = 4 -} jsmntype_t; - -enum jsmnerr { - /* Not enough tokens were provided */ - JSMN_ERROR_NOMEM = -1, - /* Invalid character inside JSON string */ - JSMN_ERROR_INVAL = -2, - /* The string is not a full JSON packet, more bytes expected */ - JSMN_ERROR_PART = -3 -}; - -/** - * JSON token description. - * type type (object, array, string etc.) - * start start position in JSON data string - * end end position in JSON data string - */ -typedef struct { - jsmntype_t type; - int start; - int end; - int size; -#ifdef JSMN_PARENT_LINKS - int parent; -#endif -} jsmntok_t; - -/** - * JSON parser. Contains an array of token blocks available. Also stores - * the string being parsed now and current position in that string - */ -typedef struct { - unsigned int pos; /* offset in the JSON string */ - unsigned int toknext; /* next token to allocate */ - int toksuper; /* superior token node, e.g parent object or array */ -} jsmn_parser; - -/** - * Create JSON parser over an array of tokens - */ -void jsmn_init(jsmn_parser *parser); - -/** - * Run JSON parser. It parses a JSON data string into and array of tokens, each describing - * a single JSON object. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens); - -#ifdef __cplusplus -} -#endif - -#endif /* __JSMN_H_ */ diff --git a/C/inc/pairwiseAlignment.h b/C/inc/pairwiseAlignment.h deleted file mode 100644 index 545cfbc..0000000 --- a/C/inc/pairwiseAlignment.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef PAIRWISE_ALIGNMENT_H_ -#define PAIRWISE_ALIGNMENT_H_ - -#include -#include "commonC.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define PAIRWISE_MATCH 0 -#define PAIRWISE_INDEL_X 1 -#define PAIRWISE_INDEL_Y 2 - -struct AlignmentOperation { - int64_t opType; - int64_t length; - float score; -}; - -struct AlignmentOperation *constructAlignmentOperation(int64_t type, int64_t length, float score); - -void destructAlignmentOperation(struct AlignmentOperation *alignmentOperation); - -struct PairwiseAlignment { - char *contig1; - int64_t start1; - int64_t end1; - int64_t strand1; - - char *contig2; - int64_t start2; - int64_t end2; - int64_t strand2; - - float score; - struct List *operationList; -}; - -struct PairwiseAlignment *constructPairwiseAlignment(char *contig1, int64_t start1, int64_t end1, int64_t strand1, - char *contig2, int64_t start2, int64_t end2, int64_t strand2, - float score, struct List *operationList); - -void destructPairwiseAlignment(struct PairwiseAlignment *pairwiseAlignment); - - -void logPairwiseAlignment(struct PairwiseAlignment *pA); - -void checkPairwiseAlignment(struct PairwiseAlignment *pA); - -void cigarWrite(FILE *fileHandle, struct PairwiseAlignment *pA, int64_t writeProbs); - -struct PairwiseAlignment *cigarRead(FILE *fileHandle); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/sonLib.h b/C/inc/sonLib.h deleted file mode 100644 index 2b13db2..0000000 --- a/C/inc/sonLib.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLib.h - * - * Created on: 21 May 2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_H_ -#define SONLIB_H_ - -#include "sonLibTree.h" -#include "sonLibString.h" -#include "sonLibHash.h" -#include "sonLibSet.h" -#include "sonLibSortedSet.h" -#include "sonLibList.h" -#include "sonLibCommon.h" -#include "sonLibTuples.h" -#include "sonLibAlign.h" -#include "sonLibExcept.h" -#include "sonLibRandom.h" -#include "sonLibKVDatabase.h" -#include "sonLibKVDatabaseConf.h" -#include "sonLibCompression.h" -#include "sonLibFile.h" -#include "sonLibMath.h" -#include "sonLibCache.h" -#include "stGraph.h" -#include "stPosetAlignment.h" -#include "sonLibTreap.h" -#include "sonLibEulerTour.h" -#include "sonLibConnectivity.h" -#include "sonLibNaiveConnectivity.h" -#include "stMatrix.h" -#include "stPhylogeny.h" -#include "stThreadPool.h" -#include "stUnionFind.h" -#include "stSafeC.h" -#include "jsmn.h" -#include "stJson.h" -#endif /* SONLIB_H_ */ diff --git a/C/inc/sonLibAlign.h b/C/inc/sonLibAlign.h deleted file mode 100644 index 10ae6a4..0000000 --- a/C/inc/sonLibAlign.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibPairwiseAlignment.h - * - * Created on: 31 May 2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_ALIGNMENT_H_ -#define SONLIB_ALIGNMENT_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Constructs a multiple sequence alignment. Each sequence is a 'row' in the alignment, - * and has a given string identifying it, a start coordinate and a strand. - */ -stAlign *stAlign_construct(int64_t sequenceNumber, - const char *contig1, int64_t start1, int64_t strand1, ...); - -/* - * Destructs a multiple sequence alignment. - */ -void stAlign_destruct(stAlign *align); - -/* - * Add an alignment block to the multiple alignment. Length is the length of the - * alignment block, sequence number is the number of sequences in the block, first sequence - * is the index of the first row in the alignment and subsequent args (whose number - * is sequenceNumber -1) are the other rows that are part of the alignment block. - */ -void stAlign_add(stAlign *align, int64_t length, int64_t sequenceNumber, int64_t firstSeqIndex, ...); - -/* - * Returns the number of alignment blocks in the alignment. - */ -int64_t stAlign_length(stAlign *align); - -/* - * Gets an iterator over the alignment blocks. - */ -stAlignIterator *stAlign_getIterator(stAlign *align); - -/* - * Gets the next alignment block in the alignment. - */ -stAlignBlock *stAlign_getNext(stAlignIterator *iterator); - -/* - * Gets the previous alignment block in the alignment. - */ -stAlignBlock *stAlign_getPrevious(stAlignIterator *iterator); - -/* - * Copy the alignment block iterator. - */ -stAlignIterator *stAlign_copyIterator(stAlignIterator *iterator); - -/* - * Destruct the alignment block iterator. - */ -void stAlign_destructIterator(stAlignIterator *iterator); - -/* - * Get the length of the alignment block (the block is a gap less alignment, so all segments have the same length). - */ -int64_t stAlignBlock_getLength(stAlignBlock *alignBlock); - -/* - * Get the number of alignment segments in the block. - */ -int64_t stAlignBlock_getSequenceNumber(stAlignBlock *alignBlock); - -/* - * Get an alignment segment for the given index. - */ -stAlignSegment *stAlignBlock_getSegment(stAlignBlock *alignBlock, int64_t); - -/* - * Get an iterator over the alignment segments in the alignment block. - */ -stAlignBlockIterator *stAlignBlock_getIterator(stAlignBlock *alignBlock); - -/* - * Get the next alignment segment in the alignment block. - */ -stAlignSegment *stAlignBlock_getNext(stAlignBlockIterator *alignBlockIterator); - -/* - * Get the previous alignment segment in the alignment block. - */ -stAlignSegment *stAlignBlock_getPrevious(stAlignBlockIterator *alignBlockIterator); - -/* - * Copy the iterator. - */ -stAlignBlockIterator *stAlignBlock_copyIterator(stAlignBlockIterator *alignBlockIterator); - -/* - * Destruct the iterator. - */ -void stAlignBlock_destructIterator(stAlignBlockIterator *alignBlockIterator); - -/* - * Gets the alignment the alignment block is part of. - */ -stAlign *stAlignBlock_getAlignment(stAlignBlock *alignBlock); - -/* - * Get the index of the row of the alignment segment in the alignment (i.e. according to the order given in the construction). - */ -int64_t stAlignSegment_getIndex(stAlignSegment *alignSegment); - -/* - * Get the string describing the sequence the alignment segment is part of. - */ -const char *stAlignSegment_getString(stAlignSegment *alignSegment); - -/* - * Get the start index of the alignment segment in the sequence. - */ -int64_t stAlignSegment_getStart(stAlignSegment *alignSegment); - -/* - * Get the end index of the alignment segment in the sequence. - */ -int64_t stAlignSegment_getEnd(stAlignSegment *alignSegment); - -/* - * Get the strand of the alignment segment on the sequence. - */ -bool stAlignSegment_getStrand(stAlignSegment *alignSegment); - -/* - * Gets the length of the alignment segment. - */ -int64_t stAlignSegment_getLength(stAlignSegment *alignSegment); - -/* - * Gets the alignment block of the alignment segment. - */ -stAlignBlock* stAlignSegment_getAlignBlock(stAlignSegment *alignSegment); - -/////////////////////// -//I/O Functions -////////////////////// - -/* - * Read in a cigar from the file and return an alignment representing it, if we - * hit the end of the file we return NULL. An exception is thrown if we don't find - * valid input but are not at the end of the file. - */ -stAlign *stAlign_readCigar(FILE *fileHandle); - -/* - * Writes a cigar representation of the alignment to the file handle. Will throw an - * exception if the alignment is not pairwise (of two sequences). - */ -void stAlign_writeCigar(stAlign *align, FILE *fileHandle); - -/* - * Read in a MAF from the file and return an alignment representing it, if we - * hit the end of the file we return NULL. An exception is thrown if we don't find - * valid input but are not at the end of the file. - */ -stAlign *stAlign_readMAF(FILE *fileHandle); - -/* - * Writes a MAF block represention of the alignment to the file handle. - */ -void stAlign_writeMAF(stAlign *align, FILE *fileHandle); - -/* - * Read in a MAF from the file and return an alignment representing it, if we - * hit the end of the file we return NULL. An exception is thrown if we don't find - * valid input but are not at the end of the file. - */ -stAlign *stAlign_readMFA(FILE *fileHandle); - -/* - * Writes a MFA represention of the alignment to the file handle. - */ -void stAlign_writeMFA(stAlign *align, FILE *fileHandle); - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/sonLibCache.h b/C/inc/sonLibCache.h deleted file mode 100644 index 363bd67..0000000 --- a/C/inc/sonLibCache.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef SONLIB__DATABASE_H_ -#define SONLIB__DATABASE_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//Cache functions -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// - -/* - * - * Create an empty cache. - */ -stCache *stCache_construct(void); - -/* - * Destructs the cache. - */ -void stCache_destruct(stCache *cache); - -/* - * Clears the cache. - */ -void stCache_clear(stCache *cache); - -/* - * Update an existing key/value record fragment in the cache. If the record does not exist it is inserted. Throws an exception if unsuccessful. - * The offset is the start of the record fragment. - */ -void stCache_setRecord(stCache *cache, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, const void *value); - -/* - * Returns non-zero if the cache contains all of the given record fragment. If zeroBasedByteOffset=INT64_MAX and - * sizeInBytes=INT64_MAX then no overlap is required. - */ -bool stCache_containsRecord(stCache *cache, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes); - -/* - * Gets a record from the cache, given the key. This function allows the partial retrieval of a record, using the - * given offset and the size of the requested retrieval. - * The function returns NULL if the desired part of the record is not in the cache exist. - * If the sizeInBytes equals INT64_MAX then the maximal size contiguous fragment of the record is returned. - * Record size is initialised with the size of the returned buffer. - */ -void *stCache_getRecord(stCache *cache, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t *recordSize); - -/* - * Returns non-zero iff the two buffers have the same size and are identical. - */ -bool stCache_recordsIdentical(const char *value, int64_t sizeOfRecord, - const char *updatedValue, int64_t updatedSizeOfRecord); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/sonLibCommon.h b/C/inc/sonLibCommon.h deleted file mode 100644 index 03ec89c..0000000 --- a/C/inc/sonLibCommon.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibCommon.h - * - * Created on: 24 May 2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_COMMON_H_ -#define SONLIB_COMMON_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -////////////////// -//Memory allocation functions -////////////////// - -/* - * Safe malloc. - */ -void *st_malloc(size_t i); - -/* - * Safe realloc. - */ -void *st_realloc(void *buffer, size_t desiredSize); - -/* - * Safe calloc. - */ -void *st_calloc(int64_t elementNumber, size_t elementSize); - -////////////////// -//Logging / std error printing -////////////////// - -enum stLogLevel { - off, - critical, - info, - debug -}; - -/* - * Set the log level. - * off (no logging), critical (highest level, associated with unexpected stuff), info (middle level), debug (copious logging) - */ -void st_setLogLevel(enum stLogLevel level); - -/* - * Set the log level from the string. If string is null it does nothing. Must be either "off", "critical", "info" or "debug", case doesn't matter. Aborts if string is not null and not one of these cases. - */ -void st_setLogLevelFromString(const char *string); - -/* - * Get the log level. Either ST_LOGGING_OFF/INFO/DEBUG. - */ -enum stLogLevel st_getLogLevel(void); - -/* - * Print a log string with level critical. - */ -void st_logCritical(const char *string, ...); - -/* - * Print a log string with level info. - */ -void st_logInfo(const char *string, ...); - -/* - * Print a log string with level debug. - */ -void st_logDebug(const char *string, ...); - -/* - * Print a message to stderr. - */ -void st_uglyf(const char *string, ...); - -////////////////////// -//System wrapper -////////////////////// - -/* - * Run a system command, return value is exit value of command. - */ -int64_t st_system(const char *string, ...); - -////////////////////// -//Error functions.. -////////////////////// - -/* - * Print the given error message to stderr followed by a newline and exit the - * program. - */ -void st_errAbort(char *format, ...); - -/* - * Print the given error message to stderr followed the POSIX error message for the current errno, - * and then a newline and exit the. program. - */ -void st_errnoAbort(char *format, ...); - -/* - * Endianness-changing functions - * - * Since htonl is 32-bit only. NOTE: detects endianness at runtime to - * be painlessly portable, so these are moderately slower than htonl - * and friends. - */ -int64_t st_nativeInt64FromLittleEndian(int64_t in); - -int64_t st_nativeInt64ToLittleEndian(int64_t in); - -int64_t st_nativeInt64FromBigEndian(int64_t in); - -int64_t st_nativeInt64ToBigEndian(int64_t in); - -#ifdef __cplusplus -} -#endif -#endif /* SONLIBCOMMON_H_ */ diff --git a/C/inc/sonLibCompression.h b/C/inc/sonLibCompression.h deleted file mode 100644 index b00325f..0000000 --- a/C/inc/sonLibCompression.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibCompression.h - * - * Created on: 03-Sep-2010 - * Author: benedictpaten - */ - -#ifndef SONLIBCOMPRESSION_H_ -#define SONLIBCOMPRESSION_H_ - -#include "sonLibTypes.h" -#ifdef __cplusplus -extern "C" { -#endif - -//The exception string -extern const char *ST_COMPRESSION_EXCEPTION_ID; - -/* - * Compresses the data and returns it. sizeInBytes in the size of the uncompressed data array, the pointer - * compressedSizeInBytes is given the size of the compressed string. The level is a value between 0 and 10 giving the - * degree of required compression. If -1 is given then the default level is used. - */ -void *stCompression_compress(void *data, int64_t sizeInBytes, int64_t *compressedSizeInBytes, int64_t level); - -/* - * Decompresses the compressed data string of size compressedSizeInBytes, initialises the sizeInBytes point to the size - * of the decompressed string. - */ -void *stCompression_decompress(void *compressedData, int64_t compressedSizeInBytes, int64_t *sizeInBytes); - -/* - * Uses Zlib. - */ -void *stCompression_compressZlib(void *data, int64_t sizeInBytes, int64_t *compressedSizeInBytes, int64_t level); - -/* - * Uses Zlib. - */ -void *stCompression_decompressZlib(void *compressedData, int64_t compressedSizeInBytes, int64_t *sizeInBytes); - -#ifdef __cplusplus -} -#endif -#endif /* SONLIBCOMPRESSION_H_ */ diff --git a/C/inc/sonLibConnectivity.h b/C/inc/sonLibConnectivity.h deleted file mode 100644 index 45145b7..0000000 --- a/C/inc/sonLibConnectivity.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * A data structure for very efficiently keeping track of connected - * components in an undirected multigraph. - */ -#ifndef SONLIB_CONNECTIVITY_H_ -#define SONLIB_CONNECTIVITY_H_ - -/* - * Create a new graph. - */ -stConnectivity *stConnectivity_construct(void); - -/* - * Free a graph properly. - */ -void stConnectivity_destruct(stConnectivity *connectivity); - -/* - * Check whether two nodes are connected. - */ -int stConnectivity_connected(stConnectivity *connectivity, void *node1, void *node2); - -/* - * Get the edges in the graph. - */ -stEdgeContainer *stConnectivity_getEdges(stConnectivity *connectivity); - -/* - * Add a new isolated node to the graph. - */ -void stConnectivity_addNode(stConnectivity *connectivity, void *node); - -/* - * Add an edge to the graph. The two nodes must have been added - * beforehand using addNode. - */ -void stConnectivity_addEdge(stConnectivity *connectivity, void *node1, void *node2); - -/* - * Check whether the graph has at least one edge between node1 and node2. - */ -bool stConnectivity_hasEdge(stConnectivity *connectivity, void *node1, void *node2); - -/* - * Remove a single edge between node1 and node2. - */ -void stConnectivity_removeEdge(stConnectivity *connectivity, void *node1, void *node2); - -/* - * Remove a node, and all its edges, from the graph. - */ -void stConnectivity_removeNode(stConnectivity *connectivity, void *node); - -/* - * Callbacks, to be notified when certain events happen to connected components. - */ - -/* - * A new component was created. - */ -void stConnectivity_setCreationCallback(stConnectivity *connectivity, void (*callback)(void *, stConnectedComponent *), void *extraData); - -/* - * The first component was merged into the second component. - */ -void stConnectivity_setMergeCallback(stConnectivity *connectivity, void (*callback)(void *, stConnectedComponent *, stConnectedComponent *), void *extraData); - -/* - * The ends in the set were cleaved from the first component into the second, new component. - */ -void stConnectivity_setCleaveCallback(stConnectivity *connectivity, void (*callback)(void *, stConnectedComponent *, stConnectedComponent *, stSet *), void *extraData); - -/* - * A component was deleted. - */ -void stConnectivity_setDeletionCallback(stConnectivity *connectivity, void (*callback)(void *, stConnectedComponent *), void *extraData); - -stConnectedComponent *stConnectedComponent_construct(stConnectivity *connectivity, void *node); - -stConnectedComponent *stConnectivity_getConnectedComponent(stConnectivity *connectivity, void *node); - -int stConnectivity_getNComponents(stConnectivity *connectivity); - -void *stConnectedComponent_getNodeInComponent(stConnectedComponent *component); - -stConnectedComponentNodeIterator *stConnectedComponent_getNodeIterator(stConnectedComponent *component); - -void *stConnectedComponentNodeIterator_getNext(stConnectedComponentNodeIterator *it); - -void stConnectedComponentNodeIterator_destruct(stConnectedComponentNodeIterator *it); - -stConnectedComponentIterator *stConnectivity_getConnectedComponentIterator(stConnectivity *connectivity); - -stConnectedComponent *stConnectedComponentIterator_getNext(stConnectedComponentIterator *it); - -void stConnectedComponentIterator_destruct(stConnectedComponentIterator *it); -void stConnectedComponent_destruct(stConnectedComponent *comp); -stEdgeContainer *stEdgeContainer_construct(void(*destructEdge)(void *)); -void stEdgeContainer_destruct(stEdgeContainer *container); -void *stEdgeContainer_getEdge(stEdgeContainer *container, void *u, void *v); -void stEdgeContainer_deleteEdge(stEdgeContainer *container, void *u, void *v); -bool stEdgeContainer_hasEdge(stEdgeContainer *container, void *u, void *v); -void stEdgeContainer_addEdge(stEdgeContainer *container, void *u, void *v, void *edge); -stList *stEdgeContainer_getIncidentEdgeList(stEdgeContainer *container, void *v); -stEdgeContainerIterator *stEdgeContainer_getIterator(stEdgeContainer *container); -bool stEdgeContainer_getNext(stEdgeContainerIterator *it, void **node1, void **node2); -void stEdgeContainer_destructIterator(stEdgeContainerIterator *it); -#endif diff --git a/C/inc/sonLibEulerTour.h b/C/inc/sonLibEulerTour.h deleted file mode 100644 index fdfa69b..0000000 --- a/C/inc/sonLibEulerTour.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef EULER_H -#define EULER_H -stEulerVertex *stEulerVertex_construct(void *vertexID); -void stEulerVertex_destruct(stEulerVertex *vertex); -stTreap *stEulerVertex_incidentEdgeA(stEulerVertex *vertex); -stTreap *stEulerVertex_incidentEdgeB(stEulerVertex *vertex); -int stEulerVertex_connected(stEulerVertex *from, stEulerVertex *to); -int stEulerVertex_isSingleton(stEulerVertex *vertex); -//------------------------------------------------------- -stEulerHalfEdge *stEulerHalfEdge_construct(void); -void stEulerHalfEdge_destruct(stEulerHalfEdge *edge); -int stEulerHalfEdge_contains(stEulerHalfEdge *edge, stEulerVertex *vertex); -void *stEulerHalfEdge_getFrom(stEulerHalfEdge *edge); -void *stEulerHalfEdge_getTo(stEulerHalfEdge *edge); -//-------------------------------------------------- -stEulerTour *stEulerTour_construct(void); -bool stEulerTour_hasEdge(stEulerTour *et, void *u, void *v); -stEdgeContainer *stEulerTour_getEdges(stEulerTour *et); -bool stEulerTour_isSingleton(stEulerTour *et, void *v); -void *stEulerTour_getConnectedComponent(stEulerTour *et, void *v); -void stEulerTour_printTour(stEulerTour *et, void *v); -void stEulerTour_printEdgeTour(stEulerTour *et, void *v); -int stEulerTour_connected(stEulerTour *et, void *u, void *v); -int stEulerTour_size(stEulerTour *et, void *v); -int stEulerTour_getNComponents(stEulerTour *et); -stTreap *stEulerTour_findRoot(stEulerTour *et, void *v); -void *stEulerTour_findRootNode(stEulerTour *et, void *v); -stEulerVertex *stEulerTour_getVertex(stEulerTour *et, void *v); -stEulerVertex *stEulerTour_createVertex(stEulerTour *et, void *vertexID); -void stEulerTour_removeVertex(stEulerTour *et, void *vertexID); -void stEulerTour_destruct(stEulerTour *et); -void stEulerTour_makeRoot(stEulerTour *et, stEulerVertex *vertex); -void stEulerTour_link(stEulerTour *et, void *u, void *v); -void stEulerTour_cut(stEulerTour *et, void *u, void *v); -//----------------------------------------------------------- -stEulerTourIterator *stEulerTour_getIterator(stEulerTour *et, void *v); -void *stEulerTourIterator_getNext(stEulerTourIterator *it); -void stEulerTourIterator_destruct(stEulerTourIterator *it); -stSet *stEulerTour_getNodesInComponent(stEulerTour *et, void *v); -//------------------------------------------------------------- -stEulerTourEdgeIterator *stEulerTour_getEdgeIterator(stEulerTour *et, void *v); -bool stEulerTourEdgeIterator_getNext(stEulerTourEdgeIterator *it, void **node1, void **node2); -void stEulerTourEdgeIterator_destruct(stEulerTourEdgeIterator *it); -//------------------------------------------------------------ -stEulerTourComponentIterator *stEulerTour_getComponentIterator(stEulerTour *et); -void *stEulerTourComponentIterator_getNext(stEulerTourComponentIterator *it); -void stEulerTourComponentIterator_destruct(stEulerTourComponentIterator *it); -#endif diff --git a/C/inc/sonLibExcept.h b/C/inc/sonLibExcept.h deleted file mode 100644 index d71c804..0000000 --- a/C/inc/sonLibExcept.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/** - * stExcept - a C exception mechanism used by SonTrace. - * - * This provides a simple setjmp based exception mechanism for C. All errors - * in the API are reported via exceptions. An exception object, containing - * both a symbolic and natural language error description is used to represent - * errors. Exception chaining is supported. - * - * The usage idiom for catching errors is: - * \code - * stTry { - * // user code here - * } stCatch(except) { - * // user exception handling here - * stExcept_free(except); - * } stTryEnd; - * \endcode - * - * To return within the try block, \code stTryReturn(value) \endcode must - * be used. There is no macro to return within the try block without - * returning a value, as this is considered tacky. A standard - * \code return \endcode can be used in the catch block. - * - * Any variable who's scope is outside of the try block and is modified - * within the try block must be declared \code volatile \endcode. For - * example: - * \code - * volatile int cnt = 0; - * ... - * stTry { - * cnt++; - * if (cnt > 10) { - * stTryReturn(cnt); - * } - * } stCatch(except) { - * stExcept_free(except); - * return -cnt; - * } stTryEnd; - * return cnt; - * \endcode - * - * If environment variable ST_ABORT is set, throwing an error causes the - * message to be printed to stderr and an abort(), which is useful for - * stopping under a debugger. Setting ST_ABORT_UNCAUGHT environment - * causes abort only on uncaught exceptions. - * - * @defgroup CExceptions Exceptions for C - */ - -#ifndef sonLibExcept_h -#define sonLibExcept_h -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -//@{ -/// @defgroup CExcept class CExcept -/// @ingroup CExceptions -//@{ - -/** - * Construct a new stExcept object. - * - * @param id symbolic exception id. This should be a constant, static string. - * @param msg print style format used to generate errMsg - * @param args arguments to format into errMsg - * @ingroup stExcept - */ -stExcept *stExcept_newv(const char *id, const char *msg, va_list args); - -/** - * Construct a new stExcept object. - * - * @param id symbolic exception id. This should be a constant, static string. - * @param msg print style format used to generate errMsg - * @param ... arguments to format into errMsg - * @ingroup stExcept - */ -stExcept *stExcept_new(const char *id, const char *msg, ...); - -/** - * Construct a new stExcept object, setting cause. - * - * @param cause causing error cause, ownership passed to the new object. - * @param id symbolic exception id. This should be a constant, static string. - * @param msg print style format used to generate errMsg - * @param args arguments to format into errMsg - * @ingroup stExcept - */ -stExcept *stExcept_newCausev(stExcept *cause, const char *id, const char *msg, va_list args); - -/** - * Construct a new stExcept object, setting cause. - * - * @param cause causing error cause, ownership passed to the new object. - * @param id symbolic exception id. This should be a constant, static string. - * @param msg print style format used to generate errMsg - * @param ... arguments to format into errMsg - * @ingroup stExcept - */ -stExcept *stExcept_newCause(stExcept *cause, const char *id, const char *msg, ...); - -/** - * Free an stExcept object. Frees assocated causes as well. - * @ingroup stExcept - */ -void stExcept_free(stExcept *except); - -/** - * Get the id for a stExcept. - * @ingroup stExcept - */ -const char* stExcept_getId(const stExcept *except); - -/** - * Determine if the id in an exception is equal to a specified id. - * @ingroup stExcept - */ -static inline bool stExcept_idEq(const stExcept *except, const char *id) { - return strcmp(stExcept_getId(except), id) == 0; -} - -/** - * Get the message for a stExcept. - * @ingroup stExcept - */ -const char* stExcept_getMsg(const stExcept *except); - -/** - * Get the cause for a stExcept. - * @ingroup stExcept - */ -stExcept *stExcept_getCause(const stExcept *except); -//@} - -/* - * Context allocated on the stack for an exception. - * (Internal structure, don't use directly) - */ -struct _stExceptContext { - jmp_buf env; // setjmp environment - struct _stExceptContext *prev; // previous context on the stack. - stExcept *except; // exception thrown into this context -}; - -/* - * Exception content Top Of Stack. - * (Internal structure, don't use directly) - */ -extern struct _stExceptContext *_cexceptTOS; - -/// @defgroup CMacros C try/catch macros -/// @ingroup stExceptions -//@{ - -/** - * Begin a try block. - */ -#define stTry {\ - struct _stExceptContext _cexceptContext;\ - _cexceptContext.prev = _cexceptTOS;\ - _cexceptTOS = &_cexceptContext;\ - _cexceptContext.except = NULL;\ - if (setjmp(_cexceptContext.env) == 0) - -/** - * Catch following a try block. - */ -#define stCatch(exceptVar) \ - if (_cexceptTOS->except != NULL) {\ - stExcept *exceptVar = _cexceptTOS->except;\ - _cexceptTOS = _cexceptTOS->prev; - -/** - * End of try/cache block - */ -#define stTryEnd \ - stExcept_free(_cexceptContext.except);\ - } else {\ - _cexceptTOS = _cexceptTOS->prev;\ - }} - -/** - * Return a value inside of a ceTry. - */ -#define stTryReturn(val) {\ - _cexceptTOS = _cexceptTOS->prev;\ - return val;\ - } - -/** - * Raise an exception. This function is not inlined to allow setting - * breakpoints. - * @param except object describing the exception. Ownership of object - * is passed to exception mechanism. - */ -void stThrow(stExcept *except); - -/** - * Construct and raise an exception. - * @param id symbolic exception id. This should be a constant, static string. - * @param msg print style format used to generate errMsg - * @param ... arguments to format into errMsg - */ -void stThrowNew(const char *id, const char *msg, ...); - -/** - * Construct and raise an exception, setting cause. - * @param cause causing error cause, ownership passed to the new object. - * @param id symbolic exception id. This should be a constant, static string. - * @param msg print style format used to generate errMsg - * @param ... arguments to format into errMsg - */ -void stThrowNewCause(stExcept *cause, const char *id, const char *msg, ...); -//@} -//@} -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/sonLibFile.h b/C/inc/sonLibFile.h deleted file mode 100644 index 8c07fd4..0000000 --- a/C/inc/sonLibFile.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibFile.h - * - * Created on: 7 Sep 2010 - * Author: benedictpaten - */ - -#ifndef SONLIBFILE_H_ -#define SONLIBFILE_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//The exception string -extern const char *ST_FILE_EXCEPTION; - -/* - * Reads a line from a file (which may be terminated by a newline char or EOF), - * returning the line excluding the newline character. - * If the file has hit the EOF then it returns NULL. - */ -char *stFile_getLineFromFile(FILE *fileHandle); - -/* - * Joins together two strings. - */ -char *stFile_pathJoin(const char *pathPrefix, const char *pathSuffix); - -/* - * Returns non-zero iff the file exists. - */ -bool stFile_exists(const char *fileName); - -/* - * Returns non-zero iff the file is a directory. Raises an exception if the file does not exist. - */ -bool stFile_isDir(const char *fileName); - -/* - * Get list of file names (as strings) in a directory. Raises an exception if dir is not a directory. - */ -stList *stFile_getFileNamesInDirectory(const char *dir); - -/* - * Creates a directory with 777 access permissions, throws exceptions if unsuccessful. - */ -void stFile_mkdir(const char *dirName); - -/* - * Forceably remove a file. If a dir, removes dir and children. Be careful. - */ -void stFile_rmrf(const char *fileName); - - -#ifdef __cplusplus -} -#endif -#endif /* SONLIBFILE_H_ */ diff --git a/C/inc/sonLibHash.h b/C/inc/sonLibHash.h deleted file mode 100644 index 73d1a98..0000000 --- a/C/inc/sonLibHash.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef SONLIB_HASH_H_ -#define SONLIB_HASH_H_ - -/* - * sonLibHash.h - * - * Created on: 4 Apr 2010 - * Author: benedictpaten - */ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// FIXME: passing key as non-const is causing unnecessary casts - -/* - * Function which generates hash key from pointer, should work well regardless of pointer size. - */ -uint64_t stHash_pointer( const void *k ); - -/* - * Constructs hash, with no destructors for keys or values. - */ -stHash *stHash_construct(void); - -/* - * Constructs a hash with given destructors, if null then destructors are ignored - */ -stHash *stHash_construct2(void (*destructKeys)(void *), void (*destructValues)(void *)); - -/* - * Constructs a hash using the given comparison functions. - */ -stHash *stHash_construct3(uint64_t (*hashKey)(const void *), int (*hashEqualsKey)(const void *, const void *), - void (*destructKeys)(void *), void (*destructValues)(void *)); - -/* - * Destructs a hash. - */ -void stHash_destruct(stHash *hash); - -/* - * Insert element, overiding if already present. - */ -void stHash_insert(stHash *hash, void *key, void *value); - -/* - * Search for value, returns null if not present. - */ -void *stHash_search(stHash *hash, void *key); - -/* - * Removes element, returning removed element. - */ -void *stHash_remove(stHash *hash, void *key); - -/* - * Removes element, returning removed element and freeing key (using supplied function). - */ -void *stHash_removeAndFreeKey(stHash *hash, void *key); - -/* - * Returns the number of key/value pairs in the hash. - */ -int64_t stHash_size(stHash *hash); - -/* - * Returns an iterator of the keys in the hash. - */ -stHashIterator *stHash_getIterator(stHash *hash); - -/* - * Gets the next key from the iterator. - */ -void *stHash_getNext(stHashIterator *iterator); - -/* - * Duplicates the iterator. - */ -stHashIterator *stHash_copyIterator(stHashIterator *iterator); - -/* - * Destructs the iterator. - */ -void stHash_destructIterator(stHashIterator *iterator); - -/* - * Gets the keys in the hash as list. - */ -stList *stHash_getKeys(stHash *hash); - -/* - * Gets the values in the hash as a list. - */ -stList *stHash_getValues(stHash *hash); - -/* - * Useful hash keys.. - */ - -/* - * A hash function for a char string. - */ -uint64_t stHash_stringKey( const void *k ); - -/* - * A hash equals function for two char strings. - */ -int stHash_stringEqualKey( const void *key1, const void *key2 ); - -/* - * Invert the hash, such that the values become the keys and vice versa. Where there are multiple keys - * mapping to the same value, only the first encountered key is stored. - */ -stHash *stHash_invert(stHash *hash, uint64_t (*hashKey)(const void *), - int(*equalsFn)(const void *, const void *), void (*destructKeys)(void *), void (*destructValues)(void *)); - -// access to the underlying functions: -uint64_t (*stHash_getHashFunction(stHash *hash))(const void *); -int (*stHash_getEqualityFunction(stHash *hash))(const void *, const void *); -void (*stHash_getKeyDestructorFunction(stHash *hash))(void *); -void (*stHash_getValueDestructorFunction(stHash *hash))(void *); - -/* - * Print a set of statistics (load, occupied load, etc.) for the - * hash. Meant to be run from gdb to check if your hash function is - * distributing properly. - */ -void stHash_printDiagnostics(stHash *hash); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/sonLibKVDatabase.h b/C/inc/sonLibKVDatabase.h deleted file mode 100644 index d19c555..0000000 --- a/C/inc/sonLibKVDatabase.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef SONLIB_KV_DATABASE_H_ -#define SONLIB_KV_DATABASE_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// General database exception id -extern const char *ST_KV_DATABASE_EXCEPTION_ID; - -// Exception where transaction should be retried -extern const char *ST_KV_DATABASE_RETRY_TRANSACTION_EXCEPTION_ID; - -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//Database functions -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// - -/* - * Constructs a non-relational database object, using the given configuration - * information to connect to the database. Create the database if create is - * true, otherwise it must exist. - */ -stKVDatabase *stKVDatabase_construct(stKVDatabaseConf *conf, bool create); - -/* - * Destructs a database. If the destruction occurs during a transaction the transaction - * is aborted and any changes are not committed to the database. - * Also destroys any databases associated the the database. - */ -void stKVDatabase_destruct(stKVDatabase *database); - -/* - * Removes the database from the disk. Any further operations on the database will - * create an exception, so you should generally destruct the object after calling this function. - */ -void stKVDatabase_deleteFromDisk(stKVDatabase *database); - -/* - * Returns non-zero if the database contains a record with the given key. - */ -bool stKVDatabase_containsRecord(stKVDatabase *database, int64_t key); - -/* - * Add a new key/value record into the table. Values can not be null. Throws an exception if unsuccessful. - */ -void stKVDatabase_insertRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord); - -/* - * Add a new int64 key/value record into the table. Throws an exception if unsuccessful. - */ -void stKVDatabase_insertInt64(stKVDatabase *database, int64_t key, int64_t value); - -/* - * Update an existing int64 key/value record into the table. Throws an exception if unsuccessful. - */ -void stKVDatabase_updateInt64(stKVDatabase *database, int64_t key, int64_t value); - -/* - * Get a int64 key/value record from the table. Throws an exception if unsuccessful. - */ -int64_t stKVDatabase_getInt64(stKVDatabase *database, int64_t key); - -/* - * Update an existing key/value record in the table. Values can not be null. Throws an exception if unsuccessful. - */ -void stKVDatabase_updateRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord); - -/* - * Update an existing key/value record in the table. Values can not be null. If the record does not exist it is inserted. Throws an exception if unsuccessful. - */ -void stKVDatabase_setRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord); - -/* - * Takes an existing record and treats it as type int64_t, incrementing the given amount in one atomic operation. - * The result is the resulting incremented value. - */ -int64_t stKVDatabase_incrementInt64(stKVDatabase *database, int64_t key, int64_t incrementAmount); - -/* - * Creates an insert request. The value memory is copied and stored in the record, and only destroyed when freed (see stKVDatabaseBulkRequest_destruct). - */ -stKVDatabaseBulkRequest *stKVDatabaseBulkRequest_constructInsertRequest(int64_t key, const void *value, int64_t sizeOfRecord); - -/* - * Construct an update request (like stKVDatabaseBulkRequest_constructInsertRequest). - */ -stKVDatabaseBulkRequest *stKVDatabaseBulkRequest_constructUpdateRequest(int64_t key, const void *value, int64_t sizeOfRecord); - -/* - * Construct a set request (like stKVDatabaseBulkRequest_constructInsertRequest). - */ -stKVDatabaseBulkRequest *stKVDatabaseBulkRequest_constructSetRequest(int64_t key, const void *value, int64_t sizeOfRecord); - -/* - * Cleans up a kvDatabaseRecord object. - */ -void stKVDatabaseBulkRequest_destruct(stKVDatabaseBulkRequest *record); - -/* - * Updates in bulk a set of stKVDatabaseBulkRequests, represented in the list. - * Throws a KV_DATABASE exception if unsuccessful. - */ -void stKVDatabase_bulkSetRecords(stKVDatabase *database, stList *records); - -/* - * Destruct a set of records, where each record is specified by a key, encoded in a stIntTuple. - * Throws a KV_DATABASE exception if unsuccessful. - */ -void stKVDatabase_bulkRemoveRecords(stKVDatabase *database, stList *records); - -/* - * Gets a record from the database, given the key. The record is in newly allocated memory, and must be freed. - * Returns NULL if the database does not contain the given record. - */ -void *stKVDatabase_getRecord(stKVDatabase *database, int64_t key); - -/* - * Gets a record from the database, given the key. The record is in newly allocated memory, and must be freed. - * Returns NULL if the database does not contain the given record. Puts the size of the record in the in the record size field. - */ -void *stKVDatabase_getRecord2(stKVDatabase *database, int64_t key, int64_t *recordSize); - - -/* - * Construct a bulk result (like a bulk request but keys are not stored) - */ -stKVDatabaseBulkResult *stKVDatabaseBulkResult_construct(void* value, int64_t sizeOfRecord); - -/* - * Get the record and size out of the bulkResult - */ -void* stKVDatabaseBulkResult_getRecord(stKVDatabaseBulkResult* bulkResult, int64_t *sizeOfRecord); - -/* - * Destruct the bulk result - */ -void stKVDatabaseBulkResult_destruct(stKVDatabaseBulkResult* bulkResult); - -/* - * Bulk get a batch of records (stored in a list of bulk results). The nth result - * corresponds to the nth key from the input keys list. - */ -stList *stKVDatabase_bulkGetRecords(stKVDatabase *database, stList* keys); - -/* - * Bulk get a batch of records (stored in a list of bulk results) from range of keys - */ -stList *stKVDatabase_bulkGetRecordsRange(stKVDatabase *database, int64_t firstKey, int64_t numRecords); - - -/* - * Removes a record from the database. Throws an exception if unsuccessful. - */ -void stKVDatabase_removeRecord(stKVDatabase *database, int64_t key); - -/* - * Gets a record from the database, given the key. This function allows the partial retrieval of a record, using the - * given offset and the size of the requested retrieval. The function should thrpw an exception if the record does - * not exist (in contrast to stKVDatabase_getRecord) and similarly should throw an exception if the requested region lies - * outside of the bounds of the record (the total size of the record must be passed the function). - */ -void *stKVDatabase_getPartialRecord(stKVDatabase *database, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize); - -/* - * Returns number of records in database. - */ -int64_t stKVDatabase_getNumberOfRecords(stKVDatabase *database); - - -/* - * get the configuration object for the database. - */ -stKVDatabaseConf *stKVDatabase_getConf(stKVDatabase *database); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/sonLibKVDatabaseConf.h b/C/inc/sonLibKVDatabaseConf.h deleted file mode 100644 index 33ff32f..0000000 --- a/C/inc/sonLibKVDatabaseConf.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef SONLIBKVDATABASECONF_H -#define SONLIBKVDATABASECONF_H -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - stKVDatabaseTypeTokyoCabinet, - stKVDatabaseTypeKyotoTycoon, - stKVDatabaseTypeMySql, -} stKVDatabaseType; - -/* - * Construct a new database configuration object for a Tokyo Cabinet - * database. - */ -stKVDatabaseConf *stKVDatabaseConf_constructTokyoCabinet(const char *databaseDir); - -/* - * Construct a new database configuration object for a Kyoto Tycoon - * database remote object. - */ -stKVDatabaseConf *stKVDatabaseConf_constructKyotoTycoon(const char *host, unsigned port, int timeout, - int64_t maxRecordSize, int64_t maxBulkSetSize, - int64_t maxBulkSetNumRecords, - const char *databaseDir, const char* databaseName); - -/* - * Construct a new database configuration object for a MySql database. - * password maybe NULL for no password. - * port maybe 0 for the default port. - */ -stKVDatabaseConf *stKVDatabaseConf_constructMySql(const char *host, unsigned port, const char *user, const char *password, - const char *databaseName, const char *tableName); - -/* - * Decodes a simple piece of XML, structured as follows: - * - * - * - * - * - * - * Type can be "tokyo_cabinet", "mysql", or "kyoto_cabinet". If it is of that type then - * you need to include a nested tag with the parameters for that conf constructor. - * The labels for the nested tag are name value pairs (no order assumed) for the conf constructor - * (see above). The port is optional. - */ -stKVDatabaseConf *stKVDatabaseConf_constructFromString(const char *xmlString); - -/* - * Construct a new database configuration from an existing one. - */ -stKVDatabaseConf *stKVDatabaseConf_constructClone(stKVDatabaseConf *srcConf); - -/* - * Free the object. - */ -void stKVDatabaseConf_destruct(stKVDatabaseConf *conf); - -/* - * get the database type. - */ -stKVDatabaseType stKVDatabaseConf_getType(stKVDatabaseConf *conf); - -/* get the directory for file based databases */ -const char *stKVDatabaseConf_getDir(stKVDatabaseConf *conf); - -/* get the host for server based databases */ -const char *stKVDatabaseConf_getHost(stKVDatabaseConf *conf); - -/* get the port for server based databases */ -unsigned stKVDatabaseConf_getPort(stKVDatabaseConf *conf); - -/* get the remote server timeout for server based databases */ -int stKVDatabaseConf_getTimeout(stKVDatabaseConf *conf); - -/* get the maximum size in bytes of a kyoto tycoon record */ -int64_t stKVDatabaseConf_getMaxKTRecordSize(stKVDatabaseConf *conf); - -/* get the maximum size in bytes of a kyoto tycoon bulk set */ -int64_t stKVDatabaseConf_getMaxKTBulkSetSize(stKVDatabaseConf *conf); - -/* get the maximum number of records in kyoto tycoon bulk set */ -int64_t stKVDatabaseConf_getMaxKTBulkSetNumRecords(stKVDatabaseConf *conf); - -/* get the user for server based databases */ -const char *stKVDatabaseConf_getUser(stKVDatabaseConf *conf); - -/* get the password for server based databases */ -const char *stKVDatabaseConf_getPassword(stKVDatabaseConf *conf); - -/* get the SQL database for server based databases */ -const char *stKVDatabaseConf_getDatabaseName(stKVDatabaseConf *conf); - -/* get the table name for server based databases */ -const char *stKVDatabaseConf_getTableName(stKVDatabaseConf *conf); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/sonLibList.h b/C/inc/sonLibList.h deleted file mode 100644 index dd5c14c..0000000 --- a/C/inc/sonLibList.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibstList.h - * - * Created on: 24 May 2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_LIST_H_ -#define SONLIB_LIST_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Construct a stList with zero length. - * The destructor will not clean up the elements in the stList. - */ -stList *stList_construct(void); - -/* - * Construct a stList with size length. - * The destructor will not clean up the elements in the stList. - */ -stList *stList_construct2(int64_t size); - -/* - * Construct a stList with size length. - * The destructor will call the given destructElement function - * for each non-null entry in the stList. - */ -stList *stList_construct3(int64_t size, void(*destructElement)(void *)); - -/* - * Destructs the stList and, if a destructElement function was given to the constructor, - * calls the destruct element function for each non-null element in the stList. - * The list maybe NULL. - */ -void stList_destruct(stList *list); - -/* - * Returns the number of elements in the stList. The list maybe NULL, - * in which case zero is returned. This allows for NULL to be used - * as an efficient way of returning an empty list. - */ -int64_t stList_length(stList *list); - -/* - * Gets item 0 <= index < stList_length(list) from the stList. - */ -void *stList_get(stList *list, int64_t index); - -/* - * Sets the item at that position in the stList. - */ -void stList_set(stList *list, int64_t index, void *item); - -/* - * Adds the item to the end of the st_list, resizing if needed. - */ -void stList_append(stList *list, void *item); - -/* - * Adds all the elements in the second st_list to the end of the first, in order. - */ -void stList_appendAll(stList *stListToAddTo, stList *stListToAdd); - -/* - * Returns the last element in the stList. Error if stList is empty. - */ -void *stList_peek(stList *list); - -/* - * Removes the last element in the stList and returns it. - * Error if the stList is empty. - */ -void *stList_pop(stList *list); - -/* - * Removes and returns the item at the given index, returning the given item. - */ -void *stList_remove(stList *list, int64_t index); - -/* - * Removes any the first instance of this item from the given stList. - */ -void stList_removeItem(stList *list, void *item); - -/* - * Removes the first element in the stList and returns it. Creates an error if empty. - */ -void *stList_removeFirst(stList *list); - -/* - * Returns non-zero iff the stList contain one or more copies of references to the given item. - */ -int64_t stList_contains(stList *list, void *item); - -/* - * Copies the stList. Sets the given destruct item function to the new stList.. can - * be null if you want no destruction of the items in that stList. - */ -stList *stList_copy(stList *list, void(*destructItem)(void *)); - -/* - * Reverses the stList in place. - */ -void stList_reverse(stList *list); - -/* - * Gets an iterator for the stList. The list maybe NULL, in which case a - * iterator that only returns NULL is created.. This allows for NULL to be - * used as an efficient way of returning an empty list. - */ -stListIterator *stList_getIterator(stList *list); - -/* - * Destruct the stList iterator. - */ -void stList_destructIterator(stListIterator *iterator); - -/* - * Gets the next item from the iterator. - */ -void *stList_getNext(stListIterator *iterator); - -/* - * Gets the previous item from the iterator. - */ -void *stList_getPrevious(stListIterator *iterator); - -/* - * Copies the iterator. - */ -stListIterator *stList_copyIterator(stListIterator *iterator); - -/* - * Sorts the stList with the given cmpFn. - */ -void stList_sort(stList *list, int cmpFn(const void *a, const void *b)); - -/* - * Sorts the stList with the given cmpFn, passing the extra argument to the comparison function. - */ -void stList_sort2(stList *list, int cmpFn(const void *a, const void *b, const void *extraArg), const void *extraArg); - -/* - * Permutes the list, by iterating over each element and swapping it randomly with a new location. - */ -void stList_shuffle(stList *list); - -/* - * Gets a sorted set representation of the stList, using the given cmpFn as backing. The sorted set - * has no defined destruct element function, so when the sorted set is destructed the elements in it and - * in this list will not be destructed. If the cmpFn is NULL then we use the default cmpFn. - */ -stSortedSet *stList_getSortedSet(stList *list, - int(*cmpFn)(const void *a, const void *b)); - -/* - * Returns a set of the elements in a list. - */ -stSet *stList_getSet(stList *list); - -/* - * Converts list to sorted set, destroying old list in process, but transferring the destructor to the set. - */ -stSortedSet *stList_convertToSortedSet(stList *list); - -/* - * Returns a new list with elements that return 0 for the given function removed. - */ -stList *stList_filter(stList *list, bool(*fn)(void *)); - -/* - * As above, but passing along extra arg as second argument to filter fn. - */ -stList *stList_filter2(stList *list, bool(*fn)(void *, void *), void *extraArg); - -/* - * Returns a new list, identical to list, but with any elements contained in set removed. - */ -stList *stList_filterToExclude(stList *list, stSortedSet *set); - -/* - * Returns a new list, identical to list, but with any elements not contained in set removed. - */ -stList *stList_filterToInclude(stList *list, stSortedSet *set); - -/* - * Sets the destructor of the list. - */ -void stList_setDestructor(stList *list, void(*destructElement)(void *)); - -/* - * Returns new list which contains elements of the list of list concatenated in one list. - */ -stList *stList_join(stList *listOfLists); - -/* - * Replaces each element in the list by applying the mapFn to the element, also passing in the extraArg argument as the second list. - */ -void stList_mapReplace(stList *l, void *(*mapFn)(void *, void *), void *extraArg); - -#ifdef __cplusplus -} -#endif -#endif /* SONLIBLIST_H_ */ diff --git a/C/inc/sonLibMath.h b/C/inc/sonLibMath.h deleted file mode 100644 index 887fe62..0000000 --- a/C/inc/sonLibMath.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2012 by Benedict Paten (a) gmail com - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef SONLIB_MATH_H_ -#define SONLIB_MATH_H_ - -/* - * sonLibMath.h - */ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#define ST_MATH_LOG_ZERO -INFINITY - -/* - * Returns a reasonable approximation to log(exp(x) + exp(y)). - */ -double stMath_logAdd(double x, double y); - -/* - * Returns a more exact calculation log(exp(x) + exp(y)). - */ -double stMath_logAddExact(double x, double y); - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // SONLIB_MATH_H_ diff --git a/C/inc/sonLibNaiveConnectivity.h b/C/inc/sonLibNaiveConnectivity.h deleted file mode 100644 index ebd156f..0000000 --- a/C/inc/sonLibNaiveConnectivity.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef NAIVE_CONNECTIVITY_H -#define NAIVE_CONNECTIVITY_H -stNaiveConnectivity *stNaiveConnectivity_construct(void); -stSet *stNaiveConnectedComponent_getNodes(stNaiveConnectedComponent *comp); -void stNaiveConnectivity_destruct(stNaiveConnectivity *connectivity); -void stNaiveConnectivity_addNode(stNaiveConnectivity *connectivity, void *node); -void stNaiveConnectivity_addEdge(stNaiveConnectivity *connectivity, void *node1, void *node2); -bool stNaiveConnectivity_hasEdge(stNaiveConnectivity *connectivity, void *node1, void *node2); -void stNaiveConnectivity_removeEdge(stNaiveConnectivity *connectivity, void *node1, void *node2); -void stNaiveConnectivity_removeNode(stNaiveConnectivity *connectivity, void *node); -stNaiveConnectedComponent *stNaiveConnectivity_getConnectedComponent(stNaiveConnectivity - *connectivity, void *node); -stNaiveConnectedComponentNodeIterator *stNaiveConnectedComponent_getNodeIterator(stNaiveConnectedComponent - *component); -void *stNaiveConnectedComponentNodeIterator_getNext(stNaiveConnectedComponentNodeIterator *it); -void stNaiveConnectedComponentNodeIterator_destruct(stNaiveConnectedComponentNodeIterator *it); -stNaiveConnectedComponentIterator *stNaiveConnectivity_getConnectedComponentIterator(stNaiveConnectivity - *connectivity); -stNaiveConnectedComponent *stNaiveConnectedComponentIterator_getNext(stNaiveConnectedComponentIterator *it); -void stNaiveConnectedComponentIterator_destruct(stNaiveConnectedComponentIterator *it); -#endif diff --git a/C/inc/sonLibRandom.h b/C/inc/sonLibRandom.h deleted file mode 100644 index 01e8484..0000000 --- a/C/inc/sonLibRandom.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibRandom.h - * - * Created on: 22-Jun-2010 - * Author: benedictpaten - */ - -#ifndef SONLIBRANDOM_H_ -#define SONLIBRANDOM_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -//The exception string -extern const char *RANDOM_EXCEPTION_ID; - -////////////////////// -//Random number functions -////////////////////// - -/* - * Seed the random number generator. - */ -void st_randomSeed(int64_t seed); - -/* - * Returns a random value in the range min (inclusive) to max (exclusive), where min < max. - */ -int64_t st_randomInt(int64_t min, int64_t max); - -/* - * Like st_randomInt, but for 64 bit integers. - */ -int64_t st_randomInt64(int64_t min, int64_t max); - -/* - * Returns a random value between 0.0 (inclusive) and 1.0 (exclusive). - */ -double st_random(void); - -/* - * Returns a random value from a list. - */ -void *st_randomChoice(stList *list); - -/* - * Gets a random upper-case A,C,G, T character. - * If includeNs is true, may additionally return an N. - * If useLowerCase then return the character as lower case, is useRandomCase then may return either lower or upper case. - */ -char stRandom_getRandomNucleotide(bool includeNs, bool useLowerCase, bool useRandomCase); - -/* - * Get a random string of nucleotide characters using st_randomGetRandomNucleotide(), with same arguments. - */ -char *stRandom_getRandomDNAString(int64_t length, bool includeNs, bool useLowerCase, bool useRandomCase); - -#ifdef __cplusplus -} -#endif -#endif /* SONLIBRANDOM_H_ */ diff --git a/C/inc/sonLibSet.h b/C/inc/sonLibSet.h deleted file mode 100644 index 32624f9..0000000 --- a/C/inc/sonLibSet.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2012 by Dent Earl dentearl (a) gmail com - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef SONLIB_SET_H_ -#define SONLIB_SET_H_ - -/* - * sonLibSet.h - * - * Created on: 12 July 2012 - * Author: dentearl - */ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -// exception string -extern const char *SET_EXCEPTION_ID; - -/* - * Function which generates hash key from pointer, should work well regardless of pointer size. - */ -uint64_t stSet_pointer(const void *k); - -/* - * Constructs set, with no destructors for keys or values. - */ -stSet *stSet_construct(void); - -/* - * Constructs a set with given destructor, if null then destructor is ignored - */ -stSet *stSet_construct2(void (*destructKeys)(void *)); - -/* - * Constructs a set using the given comparison functions. - */ -stSet *stSet_construct3(uint64_t (*hashKey)(const void *), int (*hashEqualsKey)(const void *, const void *), - void (*destructKeys)(void *)); - -/* - * Destructs a set. - */ -void stSet_destruct(stSet *set); - -/* - * Insert element, overiding if already present. - */ -void stSet_insert(stSet *set, void *key); - -/* - * Insert all elements in setToAdd to set. - */ -void stSet_insertAll(stSet *set, stSet *setToAdd); - -/* - * Search for value, returns null if not present. - */ -void *stSet_search(stSet *set, void *key); - -/* - * Removes element, returning removed element. - */ -void *stSet_remove(stSet *set, void *key); - -/* - * Removes the given subset from the given set. - */ -void stSet_removeAll(stSet *set, stSet *subset); - -/* - * Removes element, returning removed element and freeing key (using supplied function). - */ -void *stSet_removeAndFreeKey(stSet *set, void *key); - -/* - * Returns the number of keys in the set. - */ -int64_t stSet_size(stSet *set); - -/* - * Returns an arbitrary member of the set; if empty throws a set exception. - */ -void *stSet_peek(stSet *set); - -/* - * Returns an iterator of the keys in the set. - */ -stSetIterator *stSet_getIterator(stSet *set); - -/* - * Gets the next key from the iterator. - */ -void *stSet_getNext(stSetIterator *iterator); - -/* - * Duplicates the iterator. - */ -stSetIterator *stSet_copyIterator(stSetIterator *iterator); - -/* - * Destructs the iterator. - */ -void stSet_destructIterator(stSetIterator *iterator); - -/* - * Gets the keys in the set as list. - */ -stList *stSet_getKeys(stSet *set); -stList *stSet_getList(stSet *set); - -// Set Functions -stSet *stSet_getUnion(stSet *set1, stSet *set2); -stSet *stSet_getIntersection(stSet *set1, stSet *set2); -stSet *stSet_getDifference(stSet *set1, stSet *set2); - -// Comparison functions -/* - * Returns non-zero iff set1 and set2 have equal contents. - */ -bool stSet_equals(stSet *set1, stSet *set2); - -/* - * Returns non-zero iff the putativeSubset is a subset of parentSet. - */ -bool stSet_isSubset(stSet *parentSet, stSet *putativeSubset); - -// Get access to the underlying functions -uint64_t (*stSet_getHashFunction(stSet *set))(const void *); -int (*stSet_getEqualityFunction(stSet *set))(const void *, const void *); -void (*stSet_getDestructorFunction(stSet *set))(void *); - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // SONLIB_SET_H_ diff --git a/C/inc/sonLibSortedSet.h b/C/inc/sonLibSortedSet.h deleted file mode 100644 index ef3c629..0000000 --- a/C/inc/sonLibSortedSet.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef SONLIB_SORTED_SET_H_ -#define SONLIB_SORTED_SET_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//The exception string -extern const char *SORTED_SET_EXCEPTION_ID; - -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//Sorted set functions -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// - -/* - * Constructs a sorted set, using pointer based comparison function. - */ -stSortedSet *stSortedSet_construct(void); - -/* - * Constructs a sorted set, using pointer based comparison function, - * and the given destruct element function, which will be run on each element when - * the set is destructed. - */ -stSortedSet *stSortedSet_construct2(void (*destructElementFn)(void *)); - -/* - * Constructs a sorted set, using the given comparison function and destruct element function. - * If destruct element function is null then it is ignored. - */ -stSortedSet *stSortedSet_construct3(int (*compareFn)(const void *, const void *), - void (*destructElementFn)(void *)); - -/* - * Clones the given sorted set, setting the element destructor to the given function. - */ -stSortedSet *stSortedSet_copyConstruct(stSortedSet *sortedSet, void (*destructElementFn)(void *)); - -/* - * Set the destructor for the set. - */ -void stSortedSet_setDestructor(stSortedSet *set, void (*destructElement)(void *)); - -/* - * Destructs the sorted set. Note: NOT THREAD-SAFE. - */ -void stSortedSet_destruct(stSortedSet *sortedSet); - -/* - * Inserts the object into the sorted set. - */ -void stSortedSet_insert(stSortedSet *sortedSet, void *object); - -/* - * Finds the object in the sorted set, or returns null. - */ -void *stSortedSet_search(stSortedSet *sortedSet, void *object); - -/* - * Finds the object in the the sorted set that is less than or equal to the object, or returns NULL if not found. - */ -void *stSortedSet_searchLessThanOrEqual(stSortedSet *sortedSet, void *object); - -/* - * Finds the object in the the sorted set that is less than the object, or returns NULL if not found. - */ -void *stSortedSet_searchLessThan(stSortedSet *sortedSet, void *object); - -/* - * Finds the object in the the sorted set that is greater than or equal to the object, or returns NULL if not found. - */ -void *stSortedSet_searchGreaterThanOrEqual(stSortedSet *sortedSet, void *object); - -/* - * Finds the object in the the sorted set that is greater than the object, or returns NULL if not found. - */ -void *stSortedSet_searchGreaterThan(stSortedSet *sortedSet, void *object); - -/* - * Removes and returns the object from the sorted set. NOTE: Does - * *not* call the destruct function on the object. - */ -void *stSortedSet_remove(stSortedSet *sortedSet, void *object); - -/* - * Gets the number of elements in the sorted set. - */ -int64_t stSortedSet_size(stSortedSet *sortedSet); - -/* - * Gets the first element (with lowest value), in the sorted set. - */ -void *stSortedSet_getFirst(stSortedSet *items); - -/* - * Gets the last element in the sorted set. - */ -void *stSortedSet_getLast(stSortedSet *items); - -/* - * Constructs an iterator for the sorted set. - */ -stSortedSetIterator *stSortedSet_getIterator(stSortedSet *items); - -/* - * Gets an iterator from the given object. Creates an error if the item is not in the set. - * The first value returns by the iterator will be the given item. - */ -stSortedSetIterator *stSortedSet_getIteratorFrom(stSortedSet *items, void *item); - -/* - * Returns an iterator so that the first call to previous will return the last member of the set. - */ -stSortedSetIterator *stSortedSet_getReverseIterator(stSortedSet *items); - -/* - * Destructs an iterator for the sorted set. - */ -void stSortedSet_destructIterator(stSortedSetIterator *iterator); - -/* - * Gets next element in the sorted set. - */ -void *stSortedSet_getNext(stSortedSetIterator *iterator); - -/* - * Gets the previous element in the sorted set. - */ -void *stSortedSet_getPrevious(stSortedSetIterator *iterator); - -/* - * Copies the iterator. - */ -stSortedSetIterator *stSortedSet_copyIterator(stSortedSetIterator *iterator); - -/* - * Gets a stList version of the sorted set, sorted in the order of the sorted set. - * No destructor is defined for the list, so destroying the list will not destroy - * the elements in it or the sorted set. - */ -stList *stSortedSet_getList(stSortedSet *sortedSet); - -/* - * Returns non-zero iff the two sets contain the same set of elements, in the same order (i.e. under the same comparison function). - */ -int stSortedSet_equals(stSortedSet *sortedSet1, stSortedSet *sortedSet2); - -/* - * Get the union of two sorted sets. Creates exception if they have different comparators. - */ -stSortedSet *stSortedSet_getUnion(stSortedSet *sortedSet1, stSortedSet *sortedSet2); - -/* - * Get the intersection of two sorted sets. Creates exception if they have different comparators. - */ -stSortedSet *stSortedSet_getIntersection(stSortedSet *sortedSet1, stSortedSet *sortedSet2); - -/* - * Get the set difference of sortedSet1 \ sortedSet2. Creates exception if they have different comparators. - */ -stSortedSet *stSortedSet_getDifference(stSortedSet *sortedSet1, stSortedSet *sortedSet2); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/sonLibString.h b/C/inc/sonLibString.h deleted file mode 100644 index ecd0332..0000000 --- a/C/inc/sonLibString.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * SonLibString.h - * - * Created on: 24-May-2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_STRING_H_ -#define SONLIB_STRING_H_ - -#include "sonLibTypes.h" -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Copies a string, if string is NULL, NULL is returned - */ -char *stString_copy(const char *string); - -/* - * Like printf, but into a new string. Use stString_print_r instead - * unless you absolutely need to avoid the overhead of (sometimes) - * making an extra vsnprintf call. - */ -char *stString_print(const char *string, ...); - -/* - * Like stString_print, but reentrant. - */ -char *stString_print_r(const char *string, ...); - -/* - * Compare two strings for equality. NULL is considered a valid value and - * both strings being NULL returns true. - */ -inline static bool stString_eq(const char *string1, const char *string2) { - if ((string1 == NULL) && (string2 == NULL)) { - return true; - } else if ((string1 == NULL) || (string2 == NULL)) { - return false; - } else { - return strcmp(string1, string2) == 0; - } -} - -/* - * Compare two strings for equality, ignoring case. NULL is considered a valid value and - * both strings being NULL returns true. - */ -inline static bool stString_eqcase(const char *string1, const char *string2) { - if ((string1 == NULL) && (string2 == NULL)) { - return true; - } else if ((string1 == NULL) || (string2 == NULL)) { - return false; - } else { - return strcasecmp(string1, string2) == 0; - } -} - -/* - * Parses the next word from a string, updates the string pointer and returns - * the parsed string. Delimiters are all white space characters. - */ -char *stString_getNextWord(char **string); - -/* - * Creates a new version of original string with all instances of toReplace replaced with the - * replacement string. - */ -char *stString_replace(const char *originalString, const char *toReplace, const char *replacement); - -/* - * Joins a group of strings together into one long string, efficiently. 'strings' is the - * array to join, length is the length of strings and pad is the padding to place - * between each join. - */ -char *stString_join(const char *pad, const char **strings, int64_t length); - -/* - * As stString_join, but for a stList of strings. - */ -char *stString_join2(const char *pad, stList *strings); - -/* - * Splits a string using stString_getNextWord into a bunch of tokens and returns them as a list. - */ -stList *stString_split(const char *string); - -/* - * Splits a string by a delimiter string (length > 0). Note that - * delimiters on either end of the string are still used to split into - * 0-length substrings, as in python's split method. E.g.: - * stString_splitByString("aba", "a") yields ["", "b", ""] - */ -stList *stString_splitByString(const char *string, const char *delim); - -/* - * Gets a substring of a given string. - */ -char *stString_getSubString(const char *cA, int64_t start, int64_t length); - -/* - * Gives the reverse complement of string of this string. Assumes string is DNA, - * uses iupac ambiguity characters. Preserves case. For non iupac characters the original - * character is returned. - */ -char *stString_reverseComplementString(const char *string); - -/* - * As stString_reverseComplementString, but for a single character. - */ -char stString_reverseComplementChar(char c); - -#ifdef __cplusplus -} -#endif -#endif /* SONLIBSTRING_H_ */ diff --git a/C/inc/sonLibTreap.h b/C/inc/sonLibTreap.h deleted file mode 100644 index c169ca9..0000000 --- a/C/inc/sonLibTreap.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef TREAP_H -#define TREAP_H - -struct _stTreap { - //heap property is maintained for the priority, so highest priority is at the top - //of the tree. - int priority; - - //number of nodes below and including this one - int count; - - //ordering of the keys is maintained from left to right. Keys don't have to be used - //if all insertions are done through merges, and ordering will still be maintained - //by the other operations - long key; - void *value; - - stTreap *parent; - stTreap *left; - stTreap *right; -}; - -stTreap *stTreap_construct(void *value); -void *stTreap_getValue(stTreap *node); -void stTreap_destruct(stTreap *node); -void stTreap_destructRecurse(stTreap *root); -void stTreap_nodeDestruct(stTreap *node); -void stTreap_rotateLeft(stTreap *u); -void stTreap_rotateRight(stTreap *u); -stTreap *stTreap_findRoot(stTreap *node); -char *stTreap_print(stTreap *node); -char *stTreap_printBackwards(stTreap *node); -int stTreap_size(stTreap *node); -stTreap *stTreap_binarySearch(long key, stTreap *root); -int stTreap_contains(stTreap *tree, stTreap *node); -int stTreap_depth(stTreap *node); -int stTreap_compare(stTreap* a, stTreap *b); -void stTreap_moveUp(stTreap *node); -stTreap *stTreap_insert(long key, void *value, stTreap *root); -void stTreap_moveDown(stTreap *node); -int stTreap_remove(long key, stTreap *root); -stTreap *stTreap_findMin(stTreap *node); -stTreap *stTreap_findMax(stTreap *node); -stTreap *stTreap_splitAfter(stTreap *node); -stTreap *stTreap_splitBefore(stTreap *node); -void stTreap_chooseNewPriority(stTreap *node); -stTreap *stTreap_next(stTreap *node); -stTreap *stTreap_prev(stTreap *node); -stTreap *stTreap_concat(stTreap *a, stTreap *b); -stTreap *stTreap_concatRecurse(stTreap *a, stTreap *b); - -#endif diff --git a/C/inc/sonLibTree.h b/C/inc/sonLibTree.h deleted file mode 100644 index f888cb7..0000000 --- a/C/inc/sonLibTree.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * eTree.h - * - * Created on: 21 May 2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_ETREE_H_ -#define SONLIB_ETREE_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Construct unattached eTree node. - */ -stTree *stTree_construct(void); - -/* - * Destruct the eTree node and any descendants. - */ -void stTree_destruct(stTree *eTree); - -/* - * clone a node - */ -stTree *stTree_cloneNode(stTree *node); - -/* - * Clone a tree. - */ -stTree *stTree_clone(stTree *root); - -/* - * Get the parent node. - */ -stTree *stTree_getParent(stTree *eTree); - -/* - * Set the parent node. - */ -void stTree_setParent(stTree *eTree, stTree *parent); - -/* - * Get the number of children. - */ -int64_t stTree_getChildNumber(stTree *eTree); - -/* - * Get a given child. - */ -stTree *stTree_getChild(stTree *eTree, int64_t i); - -/* - * find a child by label, returning NULL if not found. - */ -stTree *stTree_findChild(stTree *eTree, const char *label); - -/* - * Get the length of the branch. If not set will return INFINITY - */ -double stTree_getBranchLength(stTree *eTree); - -/* - * Set the branch length. - */ -void stTree_setBranchLength(stTree *eTree, double distance); - -/* - * Get the clientData object, or NULL of not set. - */ -void *stTree_getClientData(stTree *eTree); - -/* - * Set the clientData object - */ -void stTree_setClientData(stTree *eTree, void *clientData); - -/* - * Get any label associated with the branch (or NULL, if none set). - */ -const char *stTree_getLabel(stTree *eTree); - -/* - * Set the label. - */ -void stTree_setLabel(stTree *eTree, const char *label); - -/* - * Get the number of nodes in the tree, starting with the specified root. - */ -int stTree_getNumNodes(stTree *root); - -/* Compare two trees for equality. Trees must have same structure, labels and - * distances. Children must be in same order. Client data is not compared. */ -bool stTree_equals(stTree *eTree1, stTree *eTree2); - -/* sort children of each node. Useful for creating reproducible test results */ -void stTree_sortChildren(stTree *root, int cmpFn(stTree *a, stTree *b)); - -/* - * Parses the newick tree string according to the format standard (I think). - */ -stTree *stTree_parseNewickString(const char *string); - -/* - * Writes a newick tree string. - */ -char *stTree_getNewickTreeString(stTree *eTree); - -/* - * Return a new tree rooted a given distance above the given node. - * Client data is set to NULL. - */ -stTree *stTree_reRoot(stTree *node, double distanceAbove); - -/* - * Return a new tree rooted a given distance above the given node. - * Client data (if any) from the old tree is preserved. - */ -stTree *stTree_reRootAndKeepClientData(stTree *node, double distanceAbove); - -/* - * Replace the child at the given index. - */ -void stTree_setChild(stTree *tree, int64_t childIndex, stTree *newChild); - -/* - * Get the most recent common ancestor of two nodes in the same - * stTree, or NULL if they are not in the same tree. - */ -stTree *stTree_getMRCA(stTree *node1, stTree *node2); - -#ifdef __cplusplus -} -#endif -#endif /* ETREE_H_ */ diff --git a/C/inc/sonLibTuples.h b/C/inc/sonLibTuples.h deleted file mode 100644 index d7177d9..0000000 --- a/C/inc/sonLibTuples.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibTuples.h - * - * Created on: 26-May-2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_TUPLES_H_ -#define SONLIB_TUPLES_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Constructs a tuple of length int64_t integers.. be very careful that length equals the - * number of subsequent arguments.. - */ - -stIntTuple *stIntTuple_construct0(void); - -stIntTuple *stIntTuple_construct1(int64_t value); - -stIntTuple *stIntTuple_construct2(int64_t value1, int64_t value2); - -stIntTuple *stIntTuple_construct3(int64_t value1, int64_t value2, int64_t value3); - -stIntTuple *stIntTuple_construct4(int64_t value1, int64_t value2, int64_t value3, int64_t value4); - -stIntTuple *stIntTuple_construct5(int64_t value1, int64_t value2, int64_t value3, int64_t value4, int64_t value5); - -stIntTuple *stIntTuple_constructN(int64_t length, const int64_t iA[]); - -/* - * Destructs the tuple. - */ -void stIntTuple_destruct(stIntTuple *intTuple); - -/* - * Creates a hash key for the tuple. - */ -uint64_t stIntTuple_hashKey(stIntTuple *intTuple); - - -/* - * Compares two int tuples, comparing the first members of the tuple, then - * the second etc.. returning if it finds a difference, - * until one or other runs out of length. If they are equal - * for all common positions but one is longer than the other, then the shorted - * is deemed less than the longer tuple. - */ -int stIntTuple_cmpFn(stIntTuple *intTuple1, stIntTuple *intTuple2); - -/* - * Returns non zero iff stIntTuple_cmpFn(intTuple1, intTuple2) == 0. - */ -int stIntTuple_equalsFn(stIntTuple *intTuple1, stIntTuple *intTuple2); - -/* - * Returns the length of the tuple. - */ -int64_t stIntTuple_length(stIntTuple *intTuple); - -/* - * Returns the value of a position in the tuple, 0 <= index < stIntTuple_length(tuple). - */ -int64_t stIntTuple_get(stIntTuple *intTuple, int64_t index); - -/* - * The following are double variants of the above functions. - * One must be very careful to ensure that the variable arguments are of type double! - */ - -stDoubleTuple *stDoubleTuple_construct(int64_t length, ...); - -void stDoubleTuple_destruct(stDoubleTuple *doubleTuple); - -uint64_t stDoubleTuple_hashKey(stDoubleTuple *doubleTuple); - -int stDoubleTuple_cmpFn(stDoubleTuple *doubleTuple1, stDoubleTuple *doubleTuple2); - -int stDoubleTuple_equalsFn(stDoubleTuple *doubleTuple1, stDoubleTuple *doubleTuple2); - -int64_t stDoubleTuple_length(stDoubleTuple *doubleTuple); - -double stDoubleTuple_getPosition(stDoubleTuple *doubleTuple, int64_t index); - -#ifdef __cplusplus -} -#endif -#endif /* SONLIBWRAPPERS_H_ */ diff --git a/C/inc/sonLibTypes.h b/C/inc/sonLibTypes.h deleted file mode 100644 index 62bb571..0000000 --- a/C/inc/sonLibTypes.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibGlobals.h - * - * Created on: 21 May 2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_GLOBALS_H_ -#define SONLIB_GLOBALS_H_ - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#include -#include -#include -#include - -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//Basic data structure declarations (contents hidden) -//////////////////////////////////////////////// -//////////////////////////////////////////////// -//////////////////////////////////////////////// - -typedef struct _stTree stTree; -typedef struct _stHash stHash; -typedef struct _stSet stSet; -typedef struct hashtable_itr stHashIterator; -typedef struct _stSetIterator stSetIterator; -typedef struct _stSortedSet stSortedSet; -typedef struct _stSortedSetIterator stSortedSetIterator; -typedef struct _stList stList; -typedef struct _stListIterator stListIterator; -typedef int64_t stIntTuple; -typedef double stDoubleTuple; -typedef struct stExcept stExcept; -typedef struct stAlign stAlign; -typedef struct stCache stCache; -typedef struct stAlignIterator stAlignIterator; -typedef struct stAlignBlock stAlignBlock; -typedef struct stAlignBlockIterator stAlignBlockIterator; -typedef struct stAlignSegment stAlignSegment; -typedef struct stKVDatabase stKVDatabase; -typedef struct stKVDatabaseConf stKVDatabaseConf; -typedef struct stKVDatabaseBulkRequest stKVDatabaseBulkRequest; -typedef struct stKVDatabaseBulkResult stKVDatabaseBulkResult; -typedef struct _stEdge stEdge; -typedef struct _stGraph stGraph; -typedef struct _stPosetAlignment stPosetAlignment; -typedef struct _stTreap stTreap; -typedef struct _stEulerVertex stEulerVertex; -typedef struct _stEulerHalfEdge stEulerHalfEdge; -typedef struct _stEulerTour stEulerTour; -typedef struct _stEulerTourIterator stEulerTourIterator; -typedef struct _stEulerTourEdgeIterator stEulerTourEdgeIterator; -typedef struct _stEulerTourComponentIterator stEulerTourComponentIterator; -typedef struct _stConnectivity stConnectivity; -typedef struct _stConnectedComponent stConnectedComponent; -typedef struct _stConnectedComponentIterator stConnectedComponentIterator; -typedef struct _stConnectedComponentNodeIterator stConnectedComponentNodeIterator; -typedef struct _stEdgeContainer stEdgeContainer; -typedef struct _stEdgeContainerIterator stEdgeContainerIterator; -typedef struct _stIncidentEdgeList stIncidentEdgeList; -typedef struct _stNaiveConnectivity stNaiveConnectivity; -typedef struct _stNaiveConnectedComponent stNaiveConnectedComponent; -typedef struct _stNaiveConnectedComponentIterator stNaiveConnectedComponentIterator; -typedef struct _stNaiveConnectedComponentNodeIterator stNaiveConnectedComponentNodeIterator; -typedef struct _stMatrix stMatrix; - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // SONLIBGLOBALS_H_ diff --git a/C/inc/stGraph.h b/C/inc/stGraph.h deleted file mode 100644 index 1ccb5f3..0000000 --- a/C/inc/stGraph.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * stGraph.h - * - * Created on: 15 Mar 2013 - * Author: benedictpaten - */ - -#ifndef STGRAPH_H_ -#define STGRAPH_H_ - -#include "sonLibTypes.h" - -/* - * Make graph with vertices 0, 1 ... vertexNo. - */ -stGraph *stGraph_construct(int64_t vertexNo); - -void stGraph_destruct(stGraph *g); - -/* - * Number of vertices in graph. - */ -int64_t stGraph_cardinality(stGraph *g); - -/* - * Get edges incident with v, returned as linked list. - */ -stEdge *stGraph_getEdges(stGraph *graph, int64_t v); - -/* - * Gets next edge incident with vertex, or NULL if no more. - */ -stEdge *stEdge_nextEdge(stEdge *e); - -double stEdge_weight(stEdge *e); - -int64_t stEdge_to(stEdge *e); - -/* - * Adds an edge to graph. - */ -void stGraph_addEdge(stGraph *graph, int64_t v1, int64_t v2, double weight); - -/* - * Computes dijkstras, returning shortest path distances between - * chosen vertex and other vertices, as an array of doubles. - */ -double *stGraph_shortestPaths(stGraph *g, int64_t sourceVertex); - -#endif /* STGRAPH_H_ */ diff --git a/C/inc/stJson.h b/C/inc/stJson.h deleted file mode 100644 index 9389b68..0000000 --- a/C/inc/stJson.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2018 by Benedict Paten (a) gmail com - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef SONLIB_JSON_H_ -#define SONLIB_JSON_H_ - -/* - * Json parsing helper functions - */ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/* - * Convert json token into a string. - */ -char *stJson_token_tostr(char *js, jsmntok_t *t); - -int64_t stJson_parseInt(char *js, jsmntok_t *tokens, int64_t tokenIndex); - -double stJson_parseFloat(char *js, jsmntok_t *tokens, int64_t tokenIndex); - -int64_t stJson_parseFloatArray(double *toArray, int64_t toArraySize, char *js, jsmntok_t *tokens, int64_t tokenIndex); - -bool stJson_parseBool(char *js, jsmntok_t *tokens, int64_t tokenIndex); - -/* - * Returns the number of nested tokens for a given key. - */ -int64_t stJson_getNestedTokenCount(jsmntok_t *tokens, int64_t tokenIndex); - -/* - * Takes a char buffer (buf) of size r and allocates a set of tokens and mutable string copy js - * of the buffer. - */ -size_t stJson_setupParser(char *buf, size_t r, jsmntok_t **tokens, char **js); - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // SONLIB_JSON_H_ diff --git a/C/inc/stMatrix.h b/C/inc/stMatrix.h deleted file mode 100644 index 981410d..0000000 --- a/C/inc/stMatrix.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2009-2014 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * stMatrix.h Really toy matrix code. - * - * Created on: 21-May-2014 - * Author: benedictpaten - */ - -#ifndef STMATRIX_H_ -#define STMATRIX_H_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Returns an n x n double precision matrix. - */ -stMatrix *stMatrix_construct(int64_t n, int64_t m); - -void stMatrix_destruct(stMatrix *matrix); - -int64_t stMatrix_n(stMatrix *matrix); - -int64_t stMatrix_m(stMatrix *matrix); - -/* - * Gets the cell for the given indices. - */ -double *stMatrix_getCell(stMatrix *matrix, int64_t indexN, int64_t indexM); - -/* - * Adds together two matrices. - */ -stMatrix *stMatrix_add(stMatrix *matrix1, stMatrix *matrix2); - -/* - * Multiples two matrices, one of which is i x j and the other is j x k producing and i x k matrix. - */ -stMatrix *stMatrix_multiply(stMatrix *matrix1, stMatrix *matrix2); - -/* - * Multiples a an n x n square matrix with a n length column vector to produce a n length output vector. - */ -double *stMatrix_multiplySquareMatrixAndColumnVector(stMatrix *matrix1, double *vector); - -/* - * Clone the matrix. - */ -stMatrix *stMatrix_clone(stMatrix *matrix); - -/* - * Scales the values in the given matrix by the given coefficients. - */ -void stMatrix_scale(stMatrix *matrix, double scaleFactor, double addFactor); - -/* - * Returns true iff the matrices have the same dimensions and are all values are within close+/- of each other. - */ -bool stMatrix_equal(stMatrix *matrix1, stMatrix *matrix2, double close); - -/* - * Return a n*n matrix representing a Jukes-Cantor substitution matrix for n characters. - */ -stMatrix *stMatrix_jukesCantor(double distance, int64_t n); - -#ifdef __cplusplus -} -#endif -#endif /* STMATRIX_H_ */ diff --git a/C/inc/stPhylogeny.h b/C/inc/stPhylogeny.h deleted file mode 100644 index f05ce47..0000000 --- a/C/inc/stPhylogeny.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2006-2014 by Joel Armstrong & Benedict Paten - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef st_phylogeny_h_ -#define st_phylogeny_h_ - -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Used for identifying the event underlying a node in a reconciled tree. -typedef enum { - DUPLICATION, - SPECIATION, - LEAF -} stReconciliationEvent; - -// Reconciliation information. Only defined on internal nodes. -typedef struct { - stTree *species; // The node in the species tree that this node maps to. - stReconciliationEvent event; // Duplication or speciation node. -} stReconciliationInfo; - -// Data structure for storing information about a node in a -// neighbor-joined tree. -typedef struct { - int64_t matrixIndex; // = -1 if an internal node, index - // into distance matrix if a leaf. - char *leavesBelow; // leavesBelow[i] = 1 if leaf i is - // present below this node, 0 - // otherwise. Could be a bit array, - // which would make things much - // faster. - int64_t numBootstraps; // Number of bootstraps that support - // this split. - double bootstrapSupport; // Fraction of bootstraps that - // support this split. - int64_t totalNumLeaves; // Total number of leaves overall in - // the tree (which is the size of - // leavesBelow). Not strictly - // necessary, but convenient -} stIndexedTreeInfo; - -// Used as client-data on nodes in trees created/used by the -// functions in this file. -typedef struct { - stReconciliationInfo *recon; // Reconciliation info. Can be NULL. - stIndexedTreeInfo *index; // Index, in case this tree has a - // previous numbering of its - // leaves. Allows more efficient traversals. - // Can be NULL. -} stPhylogenyInfo; - -// Represents a d-split as characterized by Bandelt and Dress, 1992. -typedef struct { - stList *leftSplit; - stList *rightSplit; - double isolationIndex; -} stSplit; - -// Free a stPhylogenyInfo struct. -void stPhylogenyInfo_destruct(stPhylogenyInfo *info); - -// Free stPhylogenyInfo data on all nodes in the tree. -void stPhylogenyInfo_destructOnTree(stTree *tree); - -// Clones stPhylogenyInfo and all sub-info. -stPhylogenyInfo *stPhylogenyInfo_clone(stPhylogenyInfo *info); - -// Add valid stIndexedTreeInfo (as a subfield of stPhylogenyInfo) to a -// tree with leaves labeled 0, 1, 2, 3, etc. and with internal nodes -// unlabeled. This function will fail on trees labeled any other way. -void stPhylogeny_addStIndexedTreeInfo(stTree *tree); - -// Set (and allocate) the leavesBelow and totalNumLeaves attribute in -// the stIndexedTreeInfo for the given tree and all subtrees. -// The stIndexedTreeInfo must already be allocated! -void stPhylogeny_setLeavesBelow(stTree *tree, int64_t totalNumLeaves); - -// Return a new tree which has its partitions scored by how often they -// appear in the bootstrap. This fills in the numBootstraps and -// bootstrapSupport fields of each node. All trees must have valid -// stPhylogenyInfo. -stTree *stPhylogeny_scoreFromBootstrap(stTree *tree, stTree *bootstrap); - -// Return a new tree which has its partitions scored by how often they -// appear in the bootstraps. This fills in the numBootstraps and -// bootstrapSupport fields of each node. All trees must have valid -// stPhylogenyInfo. -stTree *stPhylogeny_scoreFromBootstraps(stTree *tree, stList *bootstraps); - -stTree *stPhylogeny_scoreReconciliationFromBootstrap(stTree *tree, - stTree *bootstrap); - -// Return a new tree which has its partitions scored by how often they -// appear with the same reconciliation in the bootstraps. Obviously, -// this is always less than or equal to the normal bootstrap -// score. This fills in the numBootstraps and bootstrapSupport fields -// of each node. All trees must have valid stPhylogenyInfo. -stTree *stPhylogeny_scoreReconciliationFromBootstraps(stTree *tree, - stList *bootstraps); - -// Only one half of the distanceMatrix is used, distances[i][j] for which i > j -// Tree returned is labeled by the indices of the distance matrix. The -// tree is rooted halfway along the longest branch if outgroups is -// NULL; otherwise, it's rooted halfway along the longest outgroup -// branch. -stTree *stPhylogeny_neighborJoin(stMatrix *distances, stList *outgroups); - -// Gets the (leaf) node corresponding to an index in the distance matrix. -// Requires an indexed tree (which has stPhylogenyInfo with non-null -// stIndexedTreeInfo.) -stTree *stPhylogeny_getLeafByIndex(stTree *tree, int64_t leafIndex); - -// Find the distance between two arbitrary nodes (which must be in the -// same tree). -// Requires an indexed tree (which has stPhylogenyInfo with non-null -// stIndexedTreeInfo.) -double stPhylogeny_distanceBetweenNodes(stTree *node1, stTree *node2); - -// Find the distance between leaves (given by their index in the -// distance matrix.) -// Requires an indexed tree (which has stPhylogenyInfo with non-null -// stIndexedTreeInfo.) -double stPhylogeny_distanceBetweenLeaves(stTree *tree, int64_t leaf1, - int64_t leaf2); - -// Return the MRCA of the given leaves. More efficient than -// stTree_getMRCA. -// Requires an indexed tree (which has stPhylogenyInfo with non-null -// stIndexedTreeInfo.) -stTree *stPhylogeny_getMRCA(stTree *tree, int64_t leaf1, int64_t leaf2); - -// Compute join costs for a species tree for use in guided -// neighbor-joining. These costs are calculated by penalizing -// according to the number of dups and losses implied by the -// reconciliation when joining two genes reconciled to certain nodes -// of the species tree. -// speciesToIndex (a blank hash) will be populated with stIntTuples -// corresponding to each species' index into the join cost matrix. -// NB: the species tree must be binary. -stMatrix *stPhylogeny_computeJoinCosts(stTree *speciesTree, - stHash *speciesToIndex, - double costPerDup, double costPerLoss); - -// Precompute an MRCA matrix to pass to guided neighbor-joining. -int64_t **stPhylogeny_getMRCAMatrix(stTree *speciesTree, stHash *speciesToIndex); - -// Neighbor joining guided by a species tree. The similarity matrix -// has entries for each i and j such that s_ij if i > j is # -// differences between i and j, i < j is # similarities between i and -// j. Join costs should be precomputed by -// stPhylogeny_computeJoinCosts. indexToSpecies is a map from matrix -// index (of the similarity matrix) to species leaves. -stTree *stPhylogeny_guidedNeighborJoining(stMatrix *distanceMatrix, - stMatrix *similarityMatrix, - stMatrix *joinCosts, - stHash *matrixIndexToJoinCostIndex, - stHash *speciesToJoinCostIndex, - int64_t **speciesMRCAMatrix, - stTree *speciesTree); - -// Reconcile a gene tree (without rerooting), set the proper -// stReconcilationInfo (as an entry of stPhylogenyInfo) as client data -// on all nodes, and optionally set the labels of the ancestors to the -// labels of their reconciliation in the species tree. -// -// The species tree must be "at-most-binary", i.e. it must have no -// nodes with more than 3 children, but may have nodes with only one -// child. -void stPhylogeny_reconcileAtMostBinary(stTree *geneTree, stHash *leafToSpecies, - bool relabelAncestors); - -// For a tree that has already been reconciled by -// reconcileAtMostBinary, calculates the number of dups and losses -// implied by the reconciliation. dups and losses must be set to 0 -// before calling. The gene-tree may have polytomies. -void stPhylogeny_reconciliationCostAtMostBinary(stTree *reconciledTree, - int64_t *dups, - int64_t *losses); - -// Return a copy of geneTree that is rooted to minimize duplications. -// The gene tree must not have any polytomies. -// NOTE: the returned tree does *not* have reconciliation info set, -// and this function will reconcile geneTree, resetting any -// reconciliation information that potentially already exists. -stTree *stPhylogeny_rootByReconciliationAtMostBinary(stTree *geneTree, - stHash *leafToSpecies); - -// Return a copy of geneTree that is rooted to minimize duplications. -// This function is slower than rootByReconciliationAtMostBinary, but -// supports gene trees with polytomies. -stTree *stPhylogeny_rootByReconciliationNaive(stTree *geneTree, stHash *leafToSpecies); - -// Reconcile a binary gene tree to a species tree that may include -// polytomies. Based on the method used by NOTUNG, described in -// Vernot, Stolzer, Goldman, Durand, J Comput Biol 2008. -void stPhylogeny_reconcileNonBinary(stTree *geneTree, stHash *leafToSpecies, - bool relabelAncestors); - -// Nearest-neighbor interchange (for strictly binary trees). Returns -// two new neighboring trees in the parameters tree1 and tree2. Does -// not modify the original tree. -void stPhylogeny_nni(stTree *anc, stTree **tree1, stTree **tree2); - -// Get the non-trivial d-splits as described in Bandelt and Dress, -// 1992. The "relaxed" parameter, if true, uses the condition stated -// in the paper (where the intra-split distance must not be larger -// than *both* inter-split distances), but if false, uses a stricter -// condition (that the intra-split distance must be smaller than -// *both* inter-split distances). -stList *stPhylogeny_getSplits(stMatrix *distanceMatrix, bool relaxed); - -// Build a tree greedily using the d-splits from stPhylogeny_getSplits. -stTree *stPhylogeny_greedySplitDecomposition(stMatrix *distanceMatrix, bool relaxed); - -// Apply the Jukes-Cantor distance correction to the input distance matrix. -void stPhylogeny_applyJukesCantorCorrection(stMatrix *distanceMatrix); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/stPosetAlignment.h b/C/inc/stPosetAlignment.h deleted file mode 100644 index a01bbfd..0000000 --- a/C/inc/stPosetAlignment.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2009-2011 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * stPosetAlignment.h - * - * Created on: 21-Jun-2010 - * Author: benedictpaten - */ - -#ifndef STPOSETALIGNMENT_H_ -#define STPOSETALIGNMENT_H_ - -#include "sonLibTypes.h" - -/* - * Constructs a poset alignment containing the given number of sequences - */ -stPosetAlignment *stPosetAlignment_construct(int64_t sequenceNumber); - -/* - * Destructs the poset alignment. - */ -void stPosetAlignment_destruct(stPosetAlignment *posetAlignment); - -/* - * Returns the number of sequences in the alignment. - */ -int64_t stPosetAlignment_getSequenceNumber(stPosetAlignment *posetAlignment); - -/* - * Returns non-zero if the pair can be added to the alignment, but does not actually add the pair to the alignment. - */ -bool stPosetAlignment_isPossible(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2, int64_t position2); - -/* - * List stPosetAlignment_isPossible, but if the return value is non-zero the pair is added to the alignment. - */ -bool stPosetAlignment_add(stPosetAlignment *posetAlignment, int64_t sequence1, int64_t position1, int64_t sequence2, int64_t position2); - -#endif /* STPOSETALIGNMENT_H_ */ diff --git a/C/inc/stSafeC.h b/C/inc/stSafeC.h deleted file mode 100644 index 74ef5a5..0000000 --- a/C/inc/stSafeC.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/** - * Wrappers for C library functions that exit on errors. - * @defgroup stSafeC Robust C library functions - */ -#ifndef stSafeC_h -#define stSafeC_h -#include -#include -#include "sonLibTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//@{ - -/** - * Exception id for numeric conversion errors. - * @ingroup - */ -//const char *ST_SAFEC_NUM_CONVERT_EXCEPTION_ID; - -/** - * Abort function that doesn't allocate any memory - * @ingroup safec - */ -void stSafeCErr(const char *msg, ...) -#if defined(__GNUC__) -__attribute__((format(printf, 1, 2))) -#endif -; - -/** - * Allocate uninitialized memory, exiting with using minimal resources if it - * can't be allocated. Use stSafeCCalloc for cleared memory. - * @ingroup stSafeC - */ -void *stSafeCMalloc(size_t size); - -/** - * Allocate zeroed memory, exiting with using minimal resources if it can't be - * allocated. Should be used for small objects - * @ingroup stSafeC - */ -void *stSafeCCalloc(size_t size); - -/** - * Reallocated memory, exiting with using minimal resources if it can't be - * allocated. - * @ingroup stSafeC - */ -void *stSafeCRealloc(void *mem, size_t size); - -/** - * wrapper around free, to be consistent with other alloc functions. - * @ingroup stSafeC - */ -static inline void stSafeCFree(void *mem) { - if (mem != NULL) { - free(mem); - } -} - -/* copy a block of memory */ -void *stSafeCCopyMem(void *mem, size_t size); - -/** - * sprintf format with buffer overflow checking. The resulting string is - * always terminated with zero byte. - * @ingroup stSafeC - */ -int stSafeCFmtv(char *buffer, int bufSize, const char *format, va_list args); - -/** - * sprintf format with buffer overflow checking. The resulting string is - * always terminated with zero byte. - * @ingroup stSafeC - */ -int stSafeCFmt(char* buffer, int bufSize, const char *format, ...) -#if defined(__GNUC__) -__attribute__((format(printf, 3, 4))) -#endif -; - -/** - * sprintf formatting, returning a dynamically allocated string. - * @ingroup stSafeC - */ -char *stSafeCDynFmtv(const char *format, va_list args); - -/** - * sprintf formatting, returning a dynamically allocated string. - * @ingroup stSafeC - */ -char *stSafeCDynFmt(const char *format, ...) -#if defined(__GNUC__) -__attribute__((format(printf, 1, 2))) -#endif -; - -/* convert a string to a 32 unsigned int, exception if invalid */ -uint64_t stSafeStrToUInt32(const char *str); - -/* convert a string to a 64 int, exception if invalid */ -int64_t stSafeStrToInt64(const char *str); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/C/inc/stSpimapLayer.h b/C/inc/stSpimapLayer.h deleted file mode 100644 index 6222569..0000000 --- a/C/inc/stSpimapLayer.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef STSPIMAPLAYER_H_ -#define STSPIMAPLAYER_H_ -// Reroot a binary gene tree against a binary species tree to minimize -// the number of dups using spimap. Uses the algorithm described in -// Zmasek & Eddy, Bioinformatics, 2001. -stTree *spimap_rootAndReconcile(stTree *geneTree, stTree *speciesTree, - stHash *leafToSpecies); - -void spimap_reconciliationCost(stTree *geneTree, stTree *speciesTree, - stHash *leafToSpecies, int64_t *dups, - int64_t *losses); - -// Reconcile a gene tree (without rerooting), set the -// stReconcilationInfo as client data on all nodes, and optionally -// set the labels of the ancestors to the labels of the species tree. -void spimap_reconcile(stTree *geneTree, stTree *speciesTree, - stHash *leafToSpecies, bool relabelAncestors); - -#endif diff --git a/C/inc/stThreadPool.h b/C/inc/stThreadPool.h deleted file mode 100644 index 53470dc..0000000 --- a/C/inc/stThreadPool.h +++ /dev/null @@ -1,52 +0,0 @@ -// A very simple pthreads thread pool implementation. -// -// A work stack feeds a number of threads. Every work unit is worked -// on by a single thread, which executes the work function, then -// fetches a new work unit when finished. -// -// Often threads only need to write once to some single "result" -// variable, after the heavy computational work is done. To avoid -// needing to manage your own locks for this simple case, an optional -// "finish" function is available, which is guaranteed to run serially -// (although the work function and main thread will still run -// alongside it). If you don't want to use a finishing function, then -// the value returned by the work function is completely ignored. -// -// Note that the work "queue" is actually a stack, not a queue. This -// shouldn't matter, as you have absolutely no ordering guarantees on -// what order the work is completed in regardless. -#ifndef SONLIB_THREADPOOL_H_ -#define SONLIB_THREADPOOL_H_ -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct _stThreadPool stThreadPool; - -// Initialize the thread pool. finishFunc can be NULL if you are -// managing your own locks for output. -stThreadPool *stThreadPool_construct(int64_t numThreads, - void *(*workFunc)(void *), - void (*finishFunc)(void *)); - -// Push work onto the stack to be consumed by a thread. -void stThreadPool_push(stThreadPool *threadPool, void *workUnit); - -// Block until all work currently in the stack is complete. Can block -// indefinitely if something goes wrong. Use stThreadPool_waitSafe to -// ensure that you can get execution back after a timeout. -void stThreadPool_wait(stThreadPool *threadPool); - -// Doesn't wait on all the work to complete, just returns whether the -// work in the stack is all done or not. -bool stThreadPool_done(stThreadPool *threadPool); - -// Destroys the thread pool and destroys all threads *without* -// checking if they are still processing work or if there is work in -// the queue. -void stThreadPool_destruct(stThreadPool *threadPool); - -#ifdef __cplusplus -} -#endif -#endif // SONLIB_THREADPOOL_H_ diff --git a/C/inc/stUnionFind.h b/C/inc/stUnionFind.h deleted file mode 100644 index 5fb6afc..0000000 --- a/C/inc/stUnionFind.h +++ /dev/null @@ -1,32 +0,0 @@ -// An implementation of a fast union-find data structure with -// link-by-rank and path compression. This is equivalent to a -// partially-dynamic version of stConnectivity. - -typedef struct _stUnionFind stUnionFind; - -typedef struct _stUnionFindIt stUnionFindIt; - -// Create an empty union-find structure. -stUnionFind *stUnionFind_construct(void); - -// Free the union-find structure. -void stUnionFind_destruct(stUnionFind *unionFind); - -// Add a new isolated component containing only "object". -void stUnionFind_add(stUnionFind *unionFind, void *object); - -// Merge two components. -void stUnionFind_union(stUnionFind *unionFind, void *object1, void *object2); - -// Find the component for this object. -void *stUnionFind_find(stUnionFind *unionFind, void *object); - -// Get an iterator over the components of the union-find. -stUnionFindIt *stUnionFind_getIterator(stUnionFind *unionFind); - -// Get a component, as a set of objects, from the iterator. -// Returns NULL at the end of iteration. -stSet *stUnionFindIt_getNext(stUnionFindIt *it); - -// Free the iterator. -void stUnionFind_destructIterator(stUnionFindIt *it); diff --git a/C/tests/allTests.c b/C/tests/allTests.c deleted file mode 100644 index 8286739..0000000 --- a/C/tests/allTests.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "sonLibGlobalsTest.h" - -CuSuite* sonLib_ETreeTestSuite(void); -CuSuite* sonLib_stStringTestSuite(void); -CuSuite* sonLib_stHashTestSuite(void); -CuSuite* sonLib_stSetTestSuite(void); -CuSuite* sonLib_stSortedSetTestSuite(void); -CuSuite* sonLib_stListTestSuite(void); -CuSuite* sonLib_stCommonTestSuite(void); -CuSuite* sonLib_stIntTuplesTestSuite(void); -CuSuite* sonLib_stDoubleTuplesTestSuite(void); -CuSuite* sonLib_stExceptTestSuite(void); -CuSuite* sonLib_stRandomTestSuite(void); -CuSuite* sonLib_stCompressionTestSuite(void); -CuSuite* sonLibFileTestSuite(void); -CuSuite* stCacheSuite(void); -CuSuite* stPosetAlignmentTestSuite(void); -CuSuite* sonLibGraphTestSuite(void); -CuSuite* sonLib_stConnectivityTestSuite(void); -CuSuite* sonLib_stTreapTestSuite(void); -CuSuite* sonLib_stEulerTestSuite(void); -CuSuite* sonLib_stEdgeContainerTestSuite(void); -CuSuite* sonLib_stMatrixTestSuite(void); -CuSuite* sonLib_stPhylogenyTestSuite(void); -CuSuite* sonLib_stThreadPoolTestSuite(void); -CuSuite* sonLib_stUnionFindTestSuite(void); - -int sonLibRunAllTests(void) { - CuString *output = CuStringNew(); - CuSuite* suite = CuSuiteNew(); - CuSuiteAddSuite(suite, sonLib_stTreapTestSuite()); - CuSuiteAddSuite(suite, sonLib_stEdgeContainerTestSuite()); - CuSuiteAddSuite(suite, sonLib_stEulerTestSuite()); - CuSuiteAddSuite(suite, sonLib_stConnectivityTestSuite()); - CuSuiteAddSuite(suite, sonLib_stThreadPoolTestSuite()); - CuSuiteAddSuite(suite, sonLib_stPhylogenyTestSuite()); - CuSuiteAddSuite(suite, sonLib_stMatrixTestSuite()); - CuSuiteAddSuite(suite, sonLibGraphTestSuite()); - CuSuiteAddSuite(suite, stPosetAlignmentTestSuite()); - CuSuiteAddSuite(suite, sonLib_stCommonTestSuite()); - CuSuiteAddSuite(suite, sonLib_ETreeTestSuite()); - CuSuiteAddSuite(suite, sonLib_stStringTestSuite()); - CuSuiteAddSuite(suite, sonLib_stIntTuplesTestSuite()); - CuSuiteAddSuite(suite, sonLib_stDoubleTuplesTestSuite()); - CuSuiteAddSuite(suite, sonLib_stHashTestSuite()); - CuSuiteAddSuite(suite, sonLib_stSetTestSuite()); - CuSuiteAddSuite(suite, sonLib_stListTestSuite()); - CuSuiteAddSuite(suite, sonLib_stSortedSetTestSuite()); - CuSuiteAddSuite(suite, sonLib_stExceptTestSuite()); - CuSuiteAddSuite(suite, sonLib_stRandomTestSuite()); - CuSuiteAddSuite(suite, sonLib_stCompressionTestSuite()); - CuSuiteAddSuite(suite, sonLibFileTestSuite()); - CuSuiteAddSuite(suite, stCacheSuite()); - CuSuiteAddSuite(suite, sonLib_stUnionFindTestSuite()); - CuSuiteRun(suite); - CuSuiteSummary(suite, output); - CuSuiteDetails(suite, output); - printf("%s\n", output->buffer); - CuStringDelete(output); - int status = suite->failCount > 0; - CuSuiteDelete(suite); - return status; -} -int main(int argc, char *argv[]) { - if(argc == 2) { - st_setLogLevelFromString(argv[1]); - } - return sonLibRunAllTests(); -} diff --git a/C/tests/cigarsTest.c b/C/tests/cigarsTest.c deleted file mode 100644 index 58cf85e..0000000 --- a/C/tests/cigarsTest.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include -#include -#include -#include - -#include "fastCMaths.h" -#include "avl.h" -#include "commonC.h" -#include "bioioC.h" -#include "pairwiseAlignment.h" - -int main(int argc, char *argv[]) { - int64_t i; - struct List *pAs; - FILE *fileHandle; - struct PairwiseAlignment *pA; - int64_t keepProbs; - - assert(argc == 3); - if(strcmp(argv[2], "True") == 0) { - keepProbs = TRUE; - } - else { - assert(strcmp(argv[2], "False") == 0); - keepProbs = FALSE; - } - - pAs = constructEmptyList(0, (void (*)(void *))destructPairwiseAlignment); - fileHandle = fopen(argv[1], "r"); - pA = cigarRead(fileHandle); - while(pA != NULL) { - listAppend(pAs, pA); - pA = cigarRead(fileHandle); - } - fclose(fileHandle); - - fileHandle = fopen(argv[1], "w"); - for(i=0; ilength; i++) { - cigarWrite(fileHandle, pAs->list[i], keepProbs); - } - fclose(fileHandle); - - return 0; -} diff --git a/C/tests/fastaCTest.c b/C/tests/fastaCTest.c deleted file mode 100644 index 643a0aa..0000000 --- a/C/tests/fastaCTest.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include -#include -#include -#include - -#include "fastCMaths.h" -#include "commonC.h" -#include "bioioC.h" - -int main(int argc, char *argv[]) { - FILE *fileHandle; - struct List *seqs; - struct List *seqLengths; - struct List *seqNames; - int64_t i; - - assert(argc == 3); - - seqs = constructEmptyList(0, free); - seqLengths = constructEmptyList(0, (void (*)(void *))destructInt); - seqNames = constructEmptyList(0, free); - - fileHandle = fopen(argv[1], "r"); - fastaRead(fileHandle, seqs, seqLengths, seqNames); - fclose(fileHandle); - - fileHandle = fopen(argv[2], "w"); - for(i=0; i < seqs->length; i++) { - assert(strlen(seqs->list[i]) == *((int64_t *)seqLengths->list[i])); - fastaWrite(seqs->list[i], seqNames->list[i], fileHandle); - } - fclose(fileHandle); - - return 0; -} diff --git a/C/tests/kt_connect_test.cpp b/C/tests/kt_connect_test.cpp deleted file mode 100644 index b63f0f1..0000000 --- a/C/tests/kt_connect_test.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// test function for increment, bulk operations - -//Database functions -#include -#include - -using namespace std; -using namespace kyototycoon; - -// main routine -int main(int argc, char** argv) { - - // create the database object - RemoteDB *rdb = new RemoteDB(); - - // open the database - if (!rdb->open("kolossus-10.kilokluster.ucsc.edu", 1978, -1)) { - cerr << "open error: " << rdb->error().name() << endl; - } - - rdb->clear(); - string value; - // arbitrary expiration time - int64_t xt = 50; - - // test integer increment function - int64_t key = 7; - size_t sizeOfKey = sizeof(uint64_t); - int64_t initialValue = 123; - int64_t incrValue = 23; - int64_t sizeOfRecord = sizeof(uint64_t); - size_t sp; - - char *record; - int64_t currValue = 0; - - cout << "adding record " << initialValue << " of size " << sizeOfRecord << endl; - - - // Normalize a 64-bit number in the native order into the network byte order. - // little endian (our x86 linux machine) to big Endian.... - int64_t KCSafeIV = kyotocabinet::hton64(initialValue); - - rdb->add((char *)&key, sizeOfKey, (const char *)&KCSafeIV, sizeOfRecord); - cerr << "add record error: " << rdb->error().name() << endl; - - record = rdb->get((char *)&key, sizeOfKey, &sp, NULL); - currValue = kyotocabinet::ntoh64(*((int64_t*)record)); - - cout << "added record " << currValue << " of size " << sp << endl; - - rdb->increment((char *)&key, sizeOfKey, incrValue, xt); - rdb->increment((char *)&key, sizeOfKey, incrValue, xt); - //450 (the existing record was not compatible). - cerr << "increment error: " << rdb->error().name() << endl; - record = rdb->get((char *)&key, sizeOfKey, &sp, NULL); - - // Denormalize a 64-bit number in the network byte order into the native order. - // (big-endian to little endian) - currValue = kyotocabinet::ntoh64(*((int64_t*)record)); - - printf("value after increment (should be 146): %d and size %d\n", currValue, sp); - - rdb->clear(); - - - printf("trying a second version of increment (flip the byte order of the incr value instead..\n"); - // increment 2 hack: - rdb->add((char *)&key, sizeOfKey, (const char *)&initialValue, sizeOfRecord); - cerr << "add record error: " << rdb->error().name() << endl; - - record = rdb->get((char *)&key, sizeOfKey, &sp, NULL); - currValue = *((uint64_t*)record); - - cout << "added record " << currValue << " of size " << sp << endl; - - int retVal = rdb->increment((char *)&key, sizeOfKey, kyotocabinet::hton64(incrValue), xt); - //450 (the existing record was not compatible). - cerr << "increment error: " << rdb->error().name() << "incr value: " << retVal << endl; - record = rdb->get((char *)&key, sizeOfKey, &sp, NULL); - - // Denormalize a 64-bit number in the network byte order into the native order. - // (big-endian to little endian) - currValue = *((uint64_t*)record); - - printf("value after increment (should be 146): %d and size %d\n", currValue, sp); - - rdb->clear(); - - /* Their CPP version is broke on little-endian (i.e. Intel) machines - // the CPP version doesn't work either - rdb->add("1", "123"); - cerr << "add record error: " << rdb->error().name() << endl; - rdb->increment("1", 23); - //450 (the existing record was not compatible). - cerr << "increment error: " << rdb->error().name() << endl; - rdb->get("1", &value); - cout << "key 1 incremented to (should be 146): " << value << endl; - - rdb->clear(); - */ - - // test bulk set operation - map recs; - int64_t key1 = 5; - int64_t key2 = 6; - int64_t key3 = 7; - - int64_t val1 = 5; - int64_t val2 = 10; - int64_t val3 = 15; - - recs.insert( pair(string((const char*)&key1, sizeof(int64_t)), string((const char *)&val1, sizeof(int64_t))) ); - recs.insert( pair(string((const char*)&key2, sizeof(int64_t)), string((const char *)&val2, sizeof(int64_t))) ); - recs.insert( pair(string((const char*)&key3, sizeof(int64_t)), string((const char *)&val3, sizeof(int64_t))) ); - retVal = rdb->set_bulk(recs, xt, true); - cerr << "retval bulk set: " << retVal << endl; - cerr << " bulk retval: " << rdb->error().name() << endl; - - // retrieve a record - record = rdb->get((const char *)&key1, sizeof(int64_t), &sp, NULL); - cout << "key 5 set to (should be 5): " << *((uint64_t*)record) << endl; - - record = rdb->get((const char *)&key2, sizeof(int64_t), &sp, NULL); - cout << "key 6 set to (should be 10): " << *((uint64_t*)record) << endl; - - record = rdb->get((const char *)&key3, sizeof(int64_t), &sp, NULL); - cout << "key 7 set to (should be 15): " << *((uint64_t*)record) << endl; - - value = ""; - - vector keys; - keys.push_back(string((const char*)&key1, sizeof(int64_t))); - keys.push_back(string((const char*)&key2, sizeof(int64_t))); - keys.push_back(string((const char*)&key3, sizeof(int64_t))); - retVal = rdb->remove_bulk(keys,true); - cerr << " bulk records removed: " << retVal << endl; - cerr << " bulk retval: " << rdb->error().name() << endl; - record = rdb->get((const char *)&key3, sizeof(int64_t), &sp, NULL); - if (record == NULL) { - cout << "record 7 deleted: success!" << endl; - } else { - cout << "record 7 not deleted: failed!" << endl; - } - - rdb->clear(); - if (!rdb->close()) { - cerr << "close error: " << rdb->error().name() << endl; - } - - return 0; -} diff --git a/C/tests/kvDatabaseTest.c b/C/tests/kvDatabaseTest.c deleted file mode 100644 index ae7a03c..0000000 --- a/C/tests/kvDatabaseTest.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * kVDatabaseTest.c - * - */ - -#include "sonLibGlobalsTest.h" -#include "kvDatabaseTestCommon.h" - -static stKVDatabaseConf *conf = NULL; -static stKVDatabase *database = NULL; - -static void teardown() { - if (database != NULL) { - stKVDatabase_deleteFromDisk(database); - stKVDatabase_destruct(database); - database = NULL; - } -} - -static void setup() { - teardown(); - database = stKVDatabase_construct(conf, true); - teardown(); - database = stKVDatabase_construct(conf, true); -} - -static void constructDestructAndDelete(CuTest *testCase) { - setup(); - //The setup and teardown functions exercise all the three named functions. - teardown(); -} - -static void readWriteAndUpdateIntRecords(CuTest *testCase) { - setup(); - CuAssertIntEquals(testCase, 0, stKVDatabase_getNumberOfRecords(database)); - //Write some int64 records - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 1)); - stKVDatabase_insertInt64(database, -10000, (int64_t)50); - stKVDatabase_insertInt64(database, 4297559944418269136, (int64_t)100); - stKVDatabase_insertInt64(database, 8457478625225021883, (int64_t)150); - CuAssertTrue(testCase, stKVDatabase_getInt64(database, -10000) == 50); - CuAssertTrue(testCase, stKVDatabase_getInt64(database, 4297559944418269136) == 100); - CuAssertTrue(testCase, stKVDatabase_getInt64(database, 8457478625225021883) == 150); - - // test update - stKVDatabase_insertInt64(database, 4, (int64_t)100); - stKVDatabase_updateInt64(database, 4, (int64_t)55); - CuAssertTrue(testCase, stKVDatabase_getInt64(database, 4) == 55); - - - //Now try removing a record - stKVDatabase_removeRecord(database, 4); - CuAssertIntEquals(testCase, 3, stKVDatabase_getNumberOfRecords(database)); - CuAssertPtrEquals(testCase, NULL, stKVDatabase_getRecord(database, 0)); - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 0)); - - teardown(); -} - -static void readWriteAndRemoveRecords(CuTest *testCase) { - setup(); - CuAssertIntEquals(testCase, 0, stKVDatabase_getNumberOfRecords(database)); - //Write some records - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, -10000)); - stKVDatabase_insertRecord(database, -10000, "Red", sizeof(char) * 4); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, -10000)); - - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 4297559944418269136)); - stKVDatabase_insertRecord(database, 4297559944418269136, "Green", sizeof(char) * 6); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, 4297559944418269136)); - - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 0)); - stKVDatabase_insertRecord(database, 0, "Black", sizeof(char) * 6); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, 0)); - - //Now read and check the records exist - CuAssertIntEquals(testCase, 3, stKVDatabase_getNumberOfRecords(database)); - CuAssertStrEquals(testCase, "Red", stKVDatabase_getRecord(database, -10000)); - CuAssertStrEquals(testCase, "Green", stKVDatabase_getRecord(database, 4297559944418269136)); - CuAssertStrEquals(testCase, "Black", stKVDatabase_getRecord(database, 0)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, -10000)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, 4297559944418269136)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, 0)); - - //Now check we can retrieve records partially - CuAssertStrEquals(testCase, "d", stKVDatabase_getPartialRecord(database, -10000, 2, 2, sizeof(char) * 4)); - CuAssertStrEquals(testCase, "ed", stKVDatabase_getPartialRecord(database, -10000, 1, 3, sizeof(char) * 4)); - CuAssertStrEquals(testCase, "Red", stKVDatabase_getPartialRecord(database, -10000, 0, 4, sizeof(char) * 4)); - char *record = stKVDatabase_getPartialRecord(database, 0, 2, 3, sizeof(char) * 6); - record[2] = '\0'; - CuAssertStrEquals(testCase, "ac", record); - - //Now try removing the records - stKVDatabase_removeRecord(database, 0); - CuAssertIntEquals(testCase, 2, stKVDatabase_getNumberOfRecords(database)); - CuAssertPtrEquals(testCase, NULL, stKVDatabase_getRecord(database, 0)); - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 0)); - //Test we get exception if we remove twice. - stTry { - stKVDatabase_removeRecord(database, 0); - CuAssertTrue(testCase, false); - } - stCatch(except) - { - CuAssertTrue(testCase, stExcept_getId(except) == ST_KV_DATABASE_EXCEPTION_ID); - }stTryEnd; - - teardown(); -} - -static void partialRecordRetrieval(CuTest *testCase) { - setup(); - - //Make some number of large records - stList *records = stList_construct3(0, free); - stList *recordSizes = stList_construct3(0, (void(*)(void *)) stIntTuple_destruct); - for (int64_t i = 0; i < 300; i++) { - int64_t size = st_randomInt(0, 80); - size = size * size * size; //Use cubic size distribution - char *randomRecord = st_malloc(size * sizeof(char)); - for (int64_t j = 0; j < size; j++) { - randomRecord[j] = (char) st_randomInt(0, 100); - } - stList_append(records, randomRecord); - stList_append(recordSizes, stIntTuple_construct1( size)); - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, i)); - stKVDatabase_insertRecord(database, i, randomRecord, size * sizeof(char)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, i)); - //st_uglyf("I am creating the record %" PRIi64 " %" PRIi64 "\n", i, size); - } - - while (st_random() > 0.001) { - int64_t recordKey = st_randomInt(0, stList_length(records)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, recordKey)); - - char *record = stList_get(records, recordKey); - int64_t size = stIntTuple_get(stList_get(recordSizes, recordKey), 0); - - //Get partial record - int64_t start = size > 0 ? st_randomInt(0, size) : 0; - int64_t partialSize = size - start > 0 ? st_randomInt(start, size) - start : 0; - assert(start >= 0); - assert(partialSize >= 0); - assert(partialSize + start <= size); - //st_uglyf("I am getting record %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 "\n", recordKey, start, partialSize, size); - char *partialRecord = stKVDatabase_getPartialRecord(database, recordKey, start * sizeof(char), - partialSize * sizeof(char), size * sizeof(char)); - - //Check they are equivalent.. - for (int64_t i = 0; i < partialSize; i++) { - if (record[start + i] != partialRecord[i]) { - st_uglyf("There was a difference %" PRIi64 " %" PRIi64 " for record %" PRIi64 " %" PRIi64 "\n", record[start + i], partialRecord[i], i, - partialSize); - } - //CuAssertTrue(testCase, record[start + i] == partialRecord[i]); - } - - //Check we can not get out of bounds.. (start less than zero) - stTry { - stKVDatabase_getPartialRecord(database, recordKey, -1, 1, size * sizeof(char)); - }stCatch(except) - { - CuAssertTrue(testCase, stExcept_getId(except) == ST_KV_DATABASE_EXCEPTION_ID); - }stTryEnd; - - //Check we can not get out of bounds.. (start greater than index start) - stTry { - stKVDatabase_getPartialRecord(database, recordKey, size, 1, size * sizeof(char)); - }stCatch(except) - { - CuAssertTrue(testCase, stExcept_getId(except) == ST_KV_DATABASE_EXCEPTION_ID); - }stTryEnd; - - //Check we can not get out of bounds.. (total size if greater than record length) - stTry { - stKVDatabase_getPartialRecord(database, recordKey, 0, size + 1, size * sizeof(char)); - }stCatch(except) - { - CuAssertTrue(testCase, stExcept_getId(except) == ST_KV_DATABASE_EXCEPTION_ID); - }stTryEnd; - - //Check we can not get non existent record - stTry { - stKVDatabase_getPartialRecord(database, 1000000, 0, size, size * sizeof(char)); - }stCatch(except) - { - CuAssertTrue(testCase, stExcept_getId(except) == ST_KV_DATABASE_EXCEPTION_ID); - }stTryEnd; - } - - stList_destruct(records); - stList_destruct(recordSizes); - - teardown(); -} - -static void testIncrementRecord(CuTest *testCase) { - /* - * Tests incrementing records - */ - setup(); - // note: record we're incrementing must be the same size (8-byte integer) as - // the one we're adding to it - int64_t i = 100; - int64_t key = 7; - stKVDatabase_insertInt64(database, key, i); - CuAssertTrue(testCase, stKVDatabase_getInt64(database, key) == 100); - - int64_t l = 10; - int64_t m = 15; - int64_t n = -25; - - CuAssertTrue(testCase, stKVDatabase_incrementInt64(database, key, l) == 110); - CuAssertTrue(testCase, stKVDatabase_getInt64(database, key) == 110); - CuAssertTrue(testCase, stKVDatabase_incrementInt64(database, key, m) == 125); - CuAssertTrue(testCase, stKVDatabase_getInt64(database, key) == 125); - CuAssertTrue(testCase, stKVDatabase_incrementInt64(database, key, n) == 100); - CuAssertTrue(testCase, stKVDatabase_getInt64(database, key) == 100); - - teardown(); -} - -static void testSetRecord(CuTest *testCase) { - /* - * Tests 'setting' records (where you don't know if it's an update or an insert). - */ - setup(); - int64_t i = 100; - stKVDatabase_setRecord(database, 1, &i, sizeof(int64_t)); - int64_t *j = stKVDatabase_getRecord(database, 1); - CuAssertTrue(testCase, i == *j); - free(j); - i = 110; - stKVDatabase_setRecord(database, 1, &i, sizeof(int64_t)); - j = stKVDatabase_getRecord(database, 1); - CuAssertTrue(testCase, i == *j); - free(j); - teardown(); -} - - -static void testBulkSetRecords(CuTest *testCase) { - /* - * Tests doing a bulk update of a set of records. - */ - setup(); - int64_t i = 100, j = 110, k = 120, l = 130; - stKVDatabase_insertRecord(database, 1, &i, sizeof(int64_t)); - - stList *requests = stList_construct3(0, (void(*)(void *)) stKVDatabaseBulkRequest_destruct); - stList_append(requests, stKVDatabaseBulkRequest_constructInsertRequest(2, &j, sizeof(int64_t))); - stList_append(requests, stKVDatabaseBulkRequest_constructSetRequest(3, &k, sizeof(int64_t))); - stList_append(requests, stKVDatabaseBulkRequest_constructUpdateRequest(1, &l, sizeof(int64_t))); - - stKVDatabase_bulkSetRecords(database, requests); - - stList_destruct(requests); - - int64_t *m = stKVDatabase_getRecord(database, 1); - CuAssertTrue(testCase, m != NULL); - CuAssertTrue(testCase, l == *m); - free(m); - - m = stKVDatabase_getRecord(database, 2); - CuAssertTrue(testCase, m != NULL); - CuAssertTrue(testCase, j == *m); - free(m); - - m = stKVDatabase_getRecord(database, 3); - CuAssertTrue(testCase, m != NULL); - CuAssertTrue(testCase, k == *m); - free(m); - - teardown(); -} - -static void testBulkGetRecords(CuTest* testCase) { - /* - * Tests the new bulk get functions - */ - setup(); - int64_t i = 100, j = 110, k = 120, l = 130; - int64_t bigRecSize = 184500800; - int64_t* m = (int64_t*)st_malloc(bigRecSize); - - int64_t ki = 4, kj = 5, kk = 3, kl = 1, km = 2; - stKVDatabase_insertRecord(database, 1, &i, sizeof(int64_t)); - - stList *requests = stList_construct3(0, (void(*)(void *)) stKVDatabaseBulkRequest_destruct); - stList_append(requests, stKVDatabaseBulkRequest_constructInsertRequest(ki, &i, sizeof(int64_t))); - stList_append(requests, stKVDatabaseBulkRequest_constructInsertRequest(kj, &j, sizeof(int64_t))); - stList_append(requests, stKVDatabaseBulkRequest_constructSetRequest(kk, &k, sizeof(int64_t))); - stList_append(requests, stKVDatabaseBulkRequest_constructUpdateRequest(kl, &l, sizeof(int64_t))); - - stKVDatabase_bulkSetRecords(database, requests); - - stList_destruct(requests); - - stKVDatabase_setRecord(database, km, m, bigRecSize); - - stList* keys = stList_construct2(5); - stList_set(keys, 0, &ki); - stList_set(keys, 1, &kj); - stList_set(keys, 2, &kk); - stList_set(keys, 3, &kl); - stList_set(keys, 4, &km); - - stList* results = stKVDatabase_bulkGetRecords(database, keys); - CuAssertTrue(testCase, stList_length(results) == 5); - - void* record; - int64_t size; - - stKVDatabaseBulkResult* res0 = (stKVDatabaseBulkResult*)stList_get(results, 0); - record = stKVDatabaseBulkResult_getRecord(res0, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, *(int64_t*)record == i && size == sizeof(int64_t)); - - stKVDatabaseBulkResult* res1 = (stKVDatabaseBulkResult*)stList_get(results, 1); - record = stKVDatabaseBulkResult_getRecord(res1, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, *(int64_t*)record == j && size == sizeof(int64_t)); - - stKVDatabaseBulkResult* res2 = (stKVDatabaseBulkResult*)stList_get(results, 2); - record = stKVDatabaseBulkResult_getRecord(res2, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, *(int64_t*)record == k && size == sizeof(int64_t)); - - stKVDatabaseBulkResult* res3 = (stKVDatabaseBulkResult*)stList_get(results, 3); - record = stKVDatabaseBulkResult_getRecord(res3, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, *(int64_t*)record == l && size == sizeof(int64_t)); - - stKVDatabaseBulkResult* res4 = (stKVDatabaseBulkResult*)stList_get(results, 4); - record = stKVDatabaseBulkResult_getRecord(res4, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, size == bigRecSize); - - stList_destruct(results); - - results = stKVDatabase_bulkGetRecordsRange(database, 1, 6); - CuAssertTrue(testCase, stList_length(results) == 6); - - res0 = (stKVDatabaseBulkResult*)stList_get(results, 0); - record = stKVDatabaseBulkResult_getRecord(res0, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, *(int64_t*)record == l && size == sizeof(int64_t)); - - res1 = (stKVDatabaseBulkResult*)stList_get(results, 1); - record = stKVDatabaseBulkResult_getRecord(res1, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, size == bigRecSize); - - res2 = (stKVDatabaseBulkResult*)stList_get(results, 2); - record = stKVDatabaseBulkResult_getRecord(res2, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, *(int64_t*)record == k && size == sizeof(int64_t)); - - res3 = (stKVDatabaseBulkResult*)stList_get(results, 3); - record = stKVDatabaseBulkResult_getRecord(res3, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, *(int64_t*)record == i && size == sizeof(int64_t)); - - res4 = (stKVDatabaseBulkResult*)stList_get(results, 4); - record = stKVDatabaseBulkResult_getRecord(res4, &size); - CuAssertTrue(testCase, record != NULL); - CuAssertTrue(testCase, *(int64_t*)record == j && size == sizeof(int64_t)); - - stKVDatabaseBulkResult* res5 = (stKVDatabaseBulkResult*)stList_get(results, 5); - record = stKVDatabaseBulkResult_getRecord(res5, &size); - CuAssertTrue(testCase, record == NULL); - - stList_destruct(results); - free(m); - teardown(); -} - -static void testBulkRemoveRecords(CuTest *testCase) { - /* - * Tests doing a bulk update of a set of records. - */ - setup(); - int64_t i = 100, j = 110, k = 120, l = 130; - stKVDatabase_insertRecord(database, 1, &i, sizeof(int64_t)); - stKVDatabase_insertRecord(database, 2, &j, sizeof(int64_t)); - stKVDatabase_insertRecord(database, 3, &k, sizeof(int64_t)); - stKVDatabase_insertRecord(database, 4, &l, sizeof(int64_t)); - stKVDatabase_insertRecord(database, 5, &i, 0); //Test null record addition - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, 1)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, 2)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, 3)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, 4)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, 5)); - CuAssertTrue(testCase, stKVDatabase_getNumberOfRecords(database) == 5); - - stList *requests = stList_construct3(0, (void(*)(void *)) stIntTuple_destruct); - - // test empty request list - stKVDatabase_bulkRemoveRecords(database, requests); - - stList_append(requests, stIntTuple_construct1( (int64_t)1)); - stList_append(requests, stIntTuple_construct1( (int64_t)2)); - stList_append(requests, stIntTuple_construct1( (int64_t)3)); - stList_append(requests, stIntTuple_construct1( (int64_t)4)); - stList_append(requests, stIntTuple_construct1( (int64_t)5)); - stKVDatabase_bulkRemoveRecords(database, requests); - - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 1)); - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 2)); - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 3)); - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 4)); - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, 5)); - CuAssertTrue(testCase, stKVDatabase_getNumberOfRecords(database) == 0); - - stList_destruct(requests); - - teardown(); -} - -/* - * Retrieves really long records from the database. - */ -static void bigRecordRetrieval(CuTest *testCase) { - setup(); - for (int64_t i = 0; i < 10; i++) { - int64_t size = st_randomInt(5000000, 10000000); - char *randomRecord = st_malloc(size * sizeof(char)); - for (int64_t j = 0; j < size; j++) { - randomRecord[j] = (char) st_randomInt(0, 100); - } - - //st_uglyf("I am inserting record %" PRIi64 " %" PRIi64 "\n", i, size); - stKVDatabase_insertRecord(database, i, randomRecord, size * sizeof(char)); - - //st_uglyf("I am creating the record %" PRIi64 " %" PRIi64 "\n", i, size); - //Check they are equivalent. - int64_t size2; - char *randomRecord2 = stKVDatabase_getRecord2(database, i, &size2); - CuAssertTrue(testCase, size == size2); - for (int64_t j = 0; j < size; j++) { - CuAssertTrue(testCase, randomRecord[j] == randomRecord2[j]); - } - } - teardown(); -} - -/* Check that all tuple records in a set are present and have the expect - * value. The expected value in the set is multiplied by valueMult to get - * the actual expected value */ -static void readWriteAndRemoveRecordsLotsCheck(CuTest *testCase, stSortedSet *set, int valueMult) { - CuAssertIntEquals(testCase, stSortedSet_size(set), stKVDatabase_getNumberOfRecords(database)); - stSortedSetIterator *it = stSortedSet_getIterator(set); - stIntTuple *tuple; - while ((tuple = stSortedSet_getNext(it)) != NULL) { - int64_t *value = (int64_t *) stKVDatabase_getRecord(database, stIntTuple_get(tuple, 0)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, stIntTuple_get(tuple, 0))); - CuAssertIntEquals(testCase, valueMult*stIntTuple_get(tuple, 0), *value); - free(value); - } - stSortedSet_destructIterator(it); -} - -static void readWriteAndRemoveRecordsLotsIteration(CuTest *testCase, int numRecords, bool reopenDatabase) { - //Make a big old list of records.. - stSortedSet *set = stSortedSet_construct3((int(*)(const void *, const void *)) stIntTuple_cmpFn, - (void(*)(void *)) stIntTuple_destruct); - while (stSortedSet_size(set) < numRecords) { - int64_t key = st_randomInt(0, 100 * numRecords); - stIntTuple *tuple = stIntTuple_construct1( key); - if (stSortedSet_search(set, tuple) == NULL) { - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, key)); - stSortedSet_insert(set, tuple); - stKVDatabase_insertRecord(database, key, &key, sizeof(int64_t)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, key)); - } else { - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, key)); - stIntTuple_destruct(tuple); // already in db - } - } - - readWriteAndRemoveRecordsLotsCheck(testCase, set, 1); - - //Update all records to negate values - stSortedSetIterator *it = stSortedSet_getIterator(set); - stIntTuple *tuple; - while ((tuple = stSortedSet_getNext(it)) != NULL) { - int64_t *value = (int64_t *) stKVDatabase_getRecord(database, stIntTuple_get(tuple, 0)); - *value *= -1; - stKVDatabase_updateRecord(database, stIntTuple_get(tuple, 0), value, sizeof(int64_t)); - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, stIntTuple_get(tuple, 0))); - free(value); - } - stSortedSet_destructIterator(it); - - readWriteAndRemoveRecordsLotsCheck(testCase, set, -1); - - //Try optionally committing the transaction and reloading the database.. - if (reopenDatabase) { - //stKVDatabase_commitTransaction(database); - stKVDatabase_destruct(database); - database = stKVDatabase_construct(conf, false); - //stKVDatabase_startTransaction(database); - } - - //Now remove each one.. - it = stSortedSet_getIterator(set); - while ((tuple = stSortedSet_getNext(it)) != NULL) { - CuAssertTrue(testCase, stKVDatabase_containsRecord(database, stIntTuple_get(tuple, 0))); - stKVDatabase_removeRecord(database, stIntTuple_get(tuple, 0)); - CuAssertTrue(testCase, !stKVDatabase_containsRecord(database, stIntTuple_get(tuple, 0))); - //Test we get exception if we remove twice. - stTry { - stKVDatabase_removeRecord(database, stIntTuple_get(tuple, 0)); - CuAssertTrue(testCase, 0); - } - stCatch(except) - { - CuAssertTrue(testCase, stExcept_getId(except) == ST_KV_DATABASE_EXCEPTION_ID); - }stTryEnd; - } - stSortedSet_destructIterator(it); - CuAssertIntEquals(testCase, 0, stKVDatabase_getNumberOfRecords(database)); - - stSortedSet_destruct(set); -} - -/* - * Tests the retrieval of lots of records. - */ -static void readWriteAndRemoveRecordsLots(CuTest *testCase) { - setup(); - readWriteAndRemoveRecordsLotsIteration(testCase, 10, false); - readWriteAndRemoveRecordsLotsIteration(testCase, 56, true); - readWriteAndRemoveRecordsLotsIteration(testCase, 123, false); - readWriteAndRemoveRecordsLotsIteration(testCase, 245, true); - teardown(); -} - -static void test_stKVDatabaseConf_constructFromString_tokyoCabinet(CuTest *testCase) { - const char *xmlTestString = - ""; - stKVDatabaseConf *conf = stKVDatabaseConf_constructFromString(xmlTestString); - CuAssertTrue(testCase, stKVDatabaseConf_getType(conf) == stKVDatabaseTypeTokyoCabinet); - CuAssertStrEquals(testCase, "foo", stKVDatabaseConf_getDir(conf)); -} - -static void test_stKVDatabaseConf_constructFromString_mysql(CuTest *testCase) { -#ifdef HAVE_MYSQL - const char *xmlTestString = - ""; - stKVDatabaseConf *conf = stKVDatabaseConf_constructFromString( - xmlTestString); - CuAssertTrue(testCase, stKVDatabaseConf_getType(conf) == stKVDatabaseTypeMySql); - CuAssertTrue(testCase, stKVDatabaseConf_getDir(conf) == NULL); - CuAssertStrEquals(testCase, "enormous", stKVDatabaseConf_getHost(conf)); - CuAssertIntEquals(testCase, 5, stKVDatabaseConf_getPort(conf)); - CuAssertStrEquals(testCase, "foo", stKVDatabaseConf_getUser(conf)); - CuAssertStrEquals(testCase, "bar", stKVDatabaseConf_getPassword(conf)); - CuAssertStrEquals(testCase, "mammals", stKVDatabaseConf_getDatabaseName(conf)); - CuAssertStrEquals(testCase, "flowers", stKVDatabaseConf_getTableName(conf)); -#endif -} - -static CuSuite* stKVDatabaseTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, readWriteAndRemoveRecords); - SUITE_ADD_TEST(suite, readWriteAndUpdateIntRecords); - SUITE_ADD_TEST(suite, readWriteAndRemoveRecordsLots); - SUITE_ADD_TEST(suite, partialRecordRetrieval); - SUITE_ADD_TEST(suite, bigRecordRetrieval); - SUITE_ADD_TEST(suite, testIncrementRecord); - SUITE_ADD_TEST(suite, testSetRecord); - SUITE_ADD_TEST(suite, testBulkRemoveRecords); - SUITE_ADD_TEST(suite, testBulkSetRecords); - SUITE_ADD_TEST(suite, testBulkGetRecords); - SUITE_ADD_TEST(suite, constructDestructAndDelete); - SUITE_ADD_TEST(suite, test_stKVDatabaseConf_constructFromString_tokyoCabinet); - SUITE_ADD_TEST(suite, test_stKVDatabaseConf_constructFromString_mysql); - return suite; -} - -static int runTests(void) { - CuString *output = CuStringNew(); - CuSuite* suite = CuSuiteNew(); - CuSuiteAddSuite(suite, stKVDatabaseTestSuite()); - - CuSuiteRun(suite); - CuSuiteSummary(suite, output); - CuSuiteDetails(suite, output); - printf("%s\n", output->buffer); - return suite->failCount > 0; -} - -int main(int argc, char * const *argv) { - const char *desc = "kvDatabaseTests [options]\n" - "\n" - "Run key/value database tests.\n"; - conf = kvDatabaseTestParseOptions(argc, argv, desc, 0, 0, NULL, NULL); - return runTests(); -} - diff --git a/C/tests/kvDatabaseTestCommon.c b/C/tests/kvDatabaseTestCommon.c deleted file mode 100644 index 7d18b8e..0000000 --- a/C/tests/kvDatabaseTestCommon.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * common code for database tests. - */ -#include "sonLibGlobalsTest.h" -#include "kvDatabaseTestCommon.h" -#include "stSafeC.h" -#include - -/* usage message and exit */ -static void usage(const char *desc) { - static const char *help = - "Options:\n" - "\n" - "-t --type=dbtype - one of 'KyotoTycoon', 'TokyoCabinet' or 'MySql'.\n" - " Values area case-insensitive, defaults to TokyoCabinet.\n" - "-d --db=database - database directory for TokyoCabinet or database name\n" - " for SQL databases. Defaults to testTCDatabase for TokyoCabinet,\n" - " SQL databases must specify.\n" - "--host=host - Tycoon or SQL database host, defaults to localhost\n" - "--port=port - Tycoon or SQL database port.\n" - "-u, --user=user - SQL database user.\n" - "-p, --pass=pass - SQL database password.\n" - "-h, --help - print this message.\n"; - fprintf(stderr, "%s\n%s\n", desc, help); - exit(1); -} - -static stKVDatabaseType parseDbType(const char *dbTypeStr) { - if (stString_eqcase(dbTypeStr, "TokyoCabinet")) { - return stKVDatabaseTypeTokyoCabinet; - } else if (stString_eqcase(dbTypeStr, "KyotoTycoon")) { - return stKVDatabaseTypeKyotoTycoon; - } else if (stString_eqcase(dbTypeStr, "MySql")) { - return stKVDatabaseTypeMySql; - } else { - fprintf(stderr, "Error: invalid value for --type: %s\n", dbTypeStr); - exit(1); - } -} - -/* Parse options for specifying database to tests. Fill in positional argument vector, setting unused ones to NULL. - * The positional and numPositionalRet maybe NULL. */ -stKVDatabaseConf *kvDatabaseTestParseOptions(int argc, char *const *argv, const char *desc, int minNumPositional, int maxNumPositional, - char **positional, int *numPositionalRet) { - static struct option longOptions[] = { - {"type", required_argument, NULL, 't'}, - {"db", required_argument, NULL, 'd'}, - {"host", required_argument, NULL, 'H'}, - {"port", required_argument, NULL, 'P'}, - {"timeout", required_argument, NULL, 'i'}, - {"maxKTRecordSize", required_argument, NULL, 'r'}, - {"maxKTBulkSetSize", required_argument, NULL, 'b'}, - {"user", required_argument, NULL, 'u'}, - {"pass", required_argument, NULL, 'p'}, - {"name", required_argument, NULL, 'n'}, - {"help", no_argument, NULL, 'h'}, - {NULL, 0, NULL, '\0'} - }; - stKVDatabaseType optType = stKVDatabaseTypeTokyoCabinet; - const char *optDb = "testTCDatabase"; - const char *optHost = "localhost"; - unsigned int optPort = 0; - int optTimeout = -1; - int64_t optMaxKTRecordSize = (int64_t) 1U << 27; - int64_t optMaxKTBulkSetSize = (int64_t) 1U << 27; - int64_t optMaxKTBulkSetNumRecords = (int64_t) 1U << 27; - const char *optUser = NULL; - const char *optPass = NULL; - const char *optName = NULL; - int optKey, optIndex; - while ((optKey = getopt_long(argc, argv, "t:d:H:P:i:r:b:u:p:h", longOptions, &optIndex)) >= 0) { - switch (optKey) { - case 't': - optType = parseDbType(optarg); - break; - case 'd': - optDb = optarg; - break; - case 'H': - optHost = optarg; - break; - case 'P': - optPort = stSafeStrToUInt32(optarg); - break; - case 'i': - optTimeout = stSafeStrToUInt32(optarg); - break; - case 'r': - optMaxKTRecordSize = stSafeStrToInt64(optarg); - break; - case 'b': - optMaxKTBulkSetSize = stSafeStrToInt64(optarg); - break; - case 'u': - optUser = optarg; - break; - case 'p': - optPass = optarg; - break; - case 'n': - optName = optarg; - break; - case 'h': - usage(desc); - break; - default: - fprintf(stderr, "Error: invalid option: %s\n", argv[optind]); - usage(desc); - } - } - int numPositional = argc - optind; - if (!((minNumPositional <= numPositional) && (numPositional <= maxNumPositional))) { - fprintf(stderr, "Error: wrong number of arguments\n"); - usage(desc); - } - if (positional != NULL) { - int i; - for (i = 0; i < numPositional; i++) { - positional[i] = argv[optind+i]; - } - for (; i < maxNumPositional; i++) { - positional[i] = NULL; - } - } - if (numPositionalRet != NULL) { - *numPositionalRet = numPositional; - } - stKVDatabaseConf *conf = NULL; - if (optType == stKVDatabaseTypeTokyoCabinet) { - conf = stKVDatabaseConf_constructTokyoCabinet(optDb); - fprintf(stderr, "running Tokyo Cabinet sonLibKVDatabase tests\n"); - } else if (optType == stKVDatabaseTypeKyotoTycoon) { - conf = stKVDatabaseConf_constructKyotoTycoon(optHost, optPort, optTimeout, - optMaxKTRecordSize, optMaxKTBulkSetSize, optMaxKTBulkSetNumRecords, optDb, optName); - fprintf(stderr, "running Kyoto Tycoon sonLibKVDatabase tests\n"); - } else if (optType == stKVDatabaseTypeMySql) { - conf = stKVDatabaseConf_constructMySql(optHost, 0, optUser, optPass, optDb, "cactusDbTest"); - fprintf(stderr, "running MySQL sonLibKVDatabase tests\n"); - } - return conf; -} - diff --git a/C/tests/kvDatabaseTestCommon.h b/C/tests/kvDatabaseTestCommon.h deleted file mode 100644 index e5b493b..0000000 --- a/C/tests/kvDatabaseTestCommon.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#ifndef kvDatabaseTestCommon_h -#define kvDatabaseTestCommon_h - -/* Parse options for specifying database to tests. Fill in positional argument vector, setting unused ones to NULL. - * The positional and numPositionalRet maybe NULL. */ -stKVDatabaseConf *kvDatabaseTestParseOptions(int argc, char *const *argv, const char *desc, int minNumPositional, int maxNumPositional, - char **positional, int *numPositionalRet); - -#endif diff --git a/C/tests/sonLibAlignTest.c b/C/tests/sonLibAlignTest.c deleted file mode 100644 index 7c651c0..0000000 --- a/C/tests/sonLibAlignTest.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibAlignTest.c - * - * Created on: 1 June 2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsTest.h" - -static void teardown() { - -} - -static void setup() { - -} - - -void test_stAlignConstruct(CuTest *testCase) { - setup(); - - teardown(); -} - - -CuSuite* sonLib_stAlignTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stAlignConstruct); - return suite; -} diff --git a/C/tests/sonLibCacheTest.c b/C/tests/sonLibCacheTest.c deleted file mode 100644 index 6e35a1f..0000000 --- a/C/tests/sonLibCacheTest.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * kVDatabaseTest.c - * - */ - -#include "sonLibGlobalsTest.h" -#include "kvDatabaseTestCommon.h" - -static stCache *cache = NULL; -static int64_t recordSize; - -static void teardown() { - if(cache != NULL) { - stCache_destruct(cache); - cache = NULL; - } -} - -static void setup() { - teardown(); - cache = stCache_construct(); -} - -static void readAndUpdateRecord(CuTest *testCase) { - setup(); - - CuAssertTrue(testCase, stCache_getRecord(cache, 1, 0, INT64_MAX, &recordSize) == NULL); - CuAssertTrue(testCase, !stCache_containsRecord(cache, 1, 0, INT64_MAX)); - - stCache_setRecord(cache, 1, 5, 6, "hello"); - stCache_setRecord(cache, 1, 12, 6, "world"); - - CuAssertTrue(testCase, stCache_getRecord(cache, 1, 0, 5, &recordSize) == NULL); //Check prefix returns false - CuAssertTrue(testCase, !stCache_containsRecord(cache, 1, 0, 5)); - - CuAssertTrue(testCase, stCache_getRecord(cache, 1, 4, 2, &recordSize) == NULL); //Check prefix overlap returns false - CuAssertTrue(testCase, !stCache_containsRecord(cache, 1, 4, 2)); - - char *s = stCache_getRecord(cache, 1, 5, 6, &recordSize); - CuAssertStrEquals(testCase, "hello", s); //Check we can get the first word - free(s); - CuAssertTrue(testCase, recordSize == 6); - CuAssertTrue(testCase, stCache_containsRecord(cache, 1, 5, 6)); - - CuAssertTrue(testCase, stCache_getRecord(cache, 1, 5, 7, &recordSize) == NULL); //Check suffix overlap returns false - CuAssertTrue(testCase, !stCache_containsRecord(cache, 1, 5, 7)); - - CuAssertTrue(testCase, stCache_getRecord(cache, 1, 11, 1, &recordSize) == NULL); //Check in between returns false - CuAssertTrue(testCase, !stCache_containsRecord(cache, 1, 11, 1)); - - CuAssertTrue(testCase, stCache_getRecord(cache, 1, 11, 2, &recordSize) == NULL); //Check prefix of world returns false - CuAssertTrue(testCase, !stCache_containsRecord(cache, 1, 11, 2)); - - s = stCache_getRecord(cache, 1, 12, 6, &recordSize); - CuAssertStrEquals(testCase, "world", s); //Get the second word - free(s); - CuAssertTrue(testCase, recordSize == 6); - CuAssertTrue(testCase, stCache_containsRecord(cache, 1, 12, 6)); - - s = stCache_getRecord(cache, 1, 17, 1, &recordSize); - CuAssertStrEquals(testCase, "", s); //Get part of the second word - free(s); - CuAssertTrue(testCase, recordSize == 1); - CuAssertTrue(testCase, stCache_containsRecord(cache, 1, 17, 1)); - - CuAssertTrue(testCase, stCache_getRecord(cache, 1, 17, 2, &recordSize) == NULL); //Check suffix overlap returns false - CuAssertTrue(testCase, !stCache_containsRecord(cache, 1, 17, 2)); - - CuAssertTrue(testCase, stCache_getRecord(cache, 1, 5, 13, &recordSize) == NULL); //Check suffix overlap returns false - CuAssertTrue(testCase, !stCache_containsRecord(cache, 1, 5, 13)); - - stCache_setRecord(cache, 1, 10, 2, " "); - - s = stCache_getRecord(cache, 1, 5, INT64_MAX, &recordSize); - CuAssertStrEquals(testCase, "hello world", s); //Check we can get the first word - free(s); - CuAssertTrue(testCase, recordSize == 13); - CuAssertTrue(testCase, stCache_containsRecord(cache, 1, 5, 13)); - - stCache_setRecord(cache, 1, 5, 6, "see ya"); - - s = stCache_getRecord(cache, 1, 5, 13, &recordSize); - CuAssertStrEquals(testCase, "see ya world", s); //Check we can get the first word - free(s); - CuAssertTrue(testCase, recordSize == 13); - CuAssertTrue(testCase, stCache_containsRecord(cache, 1, 5, 13)); - CuAssertTrue(testCase, stCache_containsRecord(cache, 1, 5, INT64_MAX)); - - stCache_clear(cache); - - CuAssertTrue(testCase, !stCache_containsRecord(cache, 1, 12, 6)); //Check its gone - - teardown(); -} - -static void readAndUpdateRecords(CuTest *testCase) { - setup(); - - stCache_setRecord(cache, 1, 0, 6, "hello"); - stCache_setRecord(cache, 1, 0, 6, "world"); - stCache_setRecord(cache, INT64_MAX-1, 0, 8, "goodbye"); - stCache_setRecord(cache, 3, 0, 6, "cruel"); - stCache_setRecord(cache, INT64_MIN, 0, 6, "earth"); - - char *s = stCache_getRecord(cache, 1, 0, INT64_MAX, &recordSize); - CuAssertStrEquals(testCase, "world", s); //Get the second word - free(s); - CuAssertTrue(testCase, recordSize == 6); - CuAssertTrue(testCase, stCache_containsRecord(cache, 1, 0, INT64_MAX)); - - s = stCache_getRecord(cache, INT64_MAX-1, 0, INT64_MAX, &recordSize); - CuAssertStrEquals(testCase, "goodbye", s); //Get the second word - free(s); - CuAssertTrue(testCase, recordSize == 8); - CuAssertTrue(testCase, stCache_containsRecord(cache, INT64_MAX-1, 0, INT64_MAX)); - - s = stCache_getRecord(cache, 3, 0, INT64_MAX, &recordSize); - CuAssertStrEquals(testCase, "cruel", s); //Get the second word - free(s); - CuAssertTrue(testCase, recordSize == 6); - CuAssertTrue(testCase, stCache_containsRecord(cache, 3, 0, INT64_MAX)); - - s = stCache_getRecord(cache, INT64_MIN, 0, INT64_MAX, &recordSize); - CuAssertStrEquals(testCase, "earth", s); //Get the second word - free(s); - CuAssertTrue(testCase, recordSize == 6); - CuAssertTrue(testCase, stCache_containsRecord(cache, INT64_MIN, 0, INT64_MAX)); - - teardown(); -} - -CuSuite* stCacheSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, readAndUpdateRecord); - SUITE_ADD_TEST(suite, readAndUpdateRecords); - - return suite; -} - - diff --git a/C/tests/sonLibCommonTest.c b/C/tests/sonLibCommonTest.c deleted file mode 100644 index 1c208fc..0000000 --- a/C/tests/sonLibCommonTest.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibCommonTest.c - * - * Created on: 24 May 2010 - * Author: benedictpaten - */ -#include "sonLibGlobalsTest.h" -#include "bioioC.h" - -static void test_st_logging(CuTest *testCase) { - /* - * This just tries printing, but it doesn't verify the output. - */ - assert(testCase != NULL); - enum stLogLevel logLevel = st_getLogLevel(); - st_setLogLevel(info); - st_logCritical("OKAY This is important, %s\n", "really"); - st_logDebug("SHOULD BE INVISIBLE Hello %s\n", "world"); - st_logInfo("OKAY Bar %s\n", "foo"); - st_setLogLevel(debug); - st_logCritical("OKAY This is important, %s\n", "really"); - st_logDebug("OKAY Hello %s\n", "world"); - st_logInfo("OKAY Bar %s\n", "foo"); - st_setLogLevel(off); - st_logCritical("SHOULD BE INVISIBLE This is important, %s\n", "really"); - st_logDebug("SHOULD BE INVISIBLE Hello %s\n", "world"); - st_logInfo("SHOULD BE INVISIBLE Bar %s\n", "foo"); - st_setLogLevel(critical); - st_logCritical("OKAY This is important, %s\n", "really"); - st_logDebug("SHOULD BE INVISIBLE Hello %s\n", "world"); - st_logInfo("SHOULD BE INVISIBLE Bar %s\n", "foo"); - st_setLogLevel(logLevel); -} - -static void test_st_system(CuTest *testCase) { - /* - * Tries running two commands, one which should pass, one which should fail. - */ - CuAssertTrue(testCase, !st_system("echo 1 > /dev/null 2>&1")); - CuAssertTrue(testCase, st_system("thisProgramDoesNotExist > /dev/null 2>&1")); -} - -static void test_fastaDecodeHeader(CuTest *testCase) { - stList *tokens = fastaDecodeHeader("a|b|c"); - CuAssertIntEquals(testCase, 3, stList_length(tokens)); - CuAssertTrue(testCase, !strcmp(stList_get(tokens, 0), "a")); - CuAssertTrue(testCase, !strcmp(stList_get(tokens, 1), "b")); - CuAssertTrue(testCase, !strcmp(stList_get(tokens, 2), "c")); - stList_destruct(tokens); - - tokens = fastaDecodeHeader("|a||b|"); - CuAssertIntEquals(testCase, 5, stList_length(tokens)); - CuAssertTrue(testCase, !strcmp(stList_get(tokens, 0), "")); - CuAssertTrue(testCase, !strcmp(stList_get(tokens, 1), "a")); - CuAssertTrue(testCase, !strcmp(stList_get(tokens, 2), "")); - CuAssertTrue(testCase, !strcmp(stList_get(tokens, 3), "b")); - CuAssertTrue(testCase, !strcmp(stList_get(tokens, 4), "")); - stList_destruct(tokens); - -} - -CuSuite* sonLib_stCommonTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_st_logging); - SUITE_ADD_TEST(suite, test_st_system); - SUITE_ADD_TEST(suite, test_fastaDecodeHeader); - return suite; -} - diff --git a/C/tests/sonLibCompressionTest.c b/C/tests/sonLibCompressionTest.c deleted file mode 100644 index 99cd3ea..0000000 --- a/C/tests/sonLibCompressionTest.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibRandomTest.c - * - * Created on: 22-Jun-2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsTest.h" -#include - -static void test_stCompression_compressAndDecompressP(CuTest *testCase, int64_t rounds, int64_t minSize, int64_t maxSize, - void *(*compress)(void *, int64_t, int64_t *, int64_t), void *(*decompress)(void *, int64_t, int64_t *)) { - /* - * Exercises the two compression functions. - */ - int64_t bytesCompressed = 0, bytesDecompressed = 0; - for(int64_t i=0; i= 0); - st_logDebug("I did a round of compression: I got %" PRIi64 " bytes to compress and %" PRIi64 " bytes compressed at level %" PRIi64 " in %f seconds\n", size, compressedSizeInBytes, level, (float)difftime(time(NULL), startTime)); - //Now decompress - int64_t size2; - char *randomString2 = decompress(compressedString, compressedSizeInBytes, &size2); - st_logDebug("I did a round of compression/decompression: I got %" PRIi64 " bytes to compress and %" PRIi64 " bytes compressed at level %" PRIi64 " in %f seconds\n", size, compressedSizeInBytes, level, (float)difftime(time(NULL), startTime)); - bytesCompressed += compressedSizeInBytes; - bytesDecompressed += size; - CuAssertTrue(testCase, size == size2); - for(int64_t j=0; j -#include - -static stConnectivity *connectivity; - -static void teardown(void); - -static void setup(void) { - teardown(); - connectivity = stConnectivity_construct(); - /* - * 1--2 - * | | - * 3--4 - * - * 5--6--7 - */ - stConnectivity_addNode(connectivity, (void *) 1); - stConnectivity_addNode(connectivity, (void *) 2); - stConnectivity_addNode(connectivity, (void *) 3); - stConnectivity_addNode(connectivity, (void *) 4); - stConnectivity_addNode(connectivity, (void *) 5); - stConnectivity_addNode(connectivity, (void *) 6); - stConnectivity_addNode(connectivity, (void *) 7); - - stConnectivity_addEdge(connectivity, (void *) 1, (void *) 2); - stConnectivity_addEdge(connectivity, (void *) 1, (void *) 3); - stConnectivity_addEdge(connectivity, (void *) 2, (void *) 4); - stConnectivity_addEdge(connectivity, (void *) 3, (void *) 4); - - stConnectivity_addEdge(connectivity, (void *) 5, (void *) 6); - stConnectivity_addEdge(connectivity, (void *) 6, (void *) 7); -} - -static void teardown(void) { - if (connectivity != NULL) { - stConnectivity_destruct(connectivity); - connectivity = NULL; - } -} - -static bool setsEqual(stSet *set1, stSet *set2) { - stSet *diff = stSet_getDifference(set1, set2); - size_t size = stSet_size(diff); - stSet_destruct(diff); - return size == 0; -} - -static void test_stConnectivity_newNodeShouldGoInANewComponent(CuTest *testCase) { - setup(); - stConnectivity_addNode(connectivity, (void *) 0xDEADBEEF); - stConnectedComponent *component = stConnectivity_getConnectedComponent(connectivity, (void *) 0xDEADBEEF); - stConnectedComponentNodeIterator *nodeIt = stConnectedComponent_getNodeIterator(component); - int64_t i = 0; - void *node; - while ((node = stConnectedComponentNodeIterator_getNext(nodeIt)) != NULL) { - i++; - CuAssertTrue(testCase, node == (void *) 0xDEADBEEF); - } - CuAssertIntEquals(testCase, 1, i); - - stConnectedComponentNodeIterator_destruct(nodeIt); - teardown(); -} - -static void test_stConnectivity_connectedComponents(CuTest *testCase) { - setup(); - - stConnectedComponentIterator *componentIt = stConnectivity_getConnectedComponentIterator(connectivity); - stList *components = stList_construct(); - stConnectedComponent *component; - while ((component = stConnectedComponentIterator_getNext(componentIt)) != NULL) { - stList_append(components, component); - } - stConnectedComponentIterator_destruct(componentIt); - - CuAssertIntEquals(testCase, 2, stList_length(components)); - - stSet *truth1 = stSet_construct(); - stSet_insert(truth1, (void *) 1); - stSet_insert(truth1, (void *) 2); - stSet_insert(truth1, (void *) 3); - stSet_insert(truth1, (void *) 4); - stSet *test1 = stSet_construct(); - stConnectedComponent *component1 = stConnectivity_getConnectedComponent(connectivity, (void *) 4); - stConnectedComponentNodeIterator *nodeIt = stConnectedComponent_getNodeIterator(component1); - void *node; - while ((node = stConnectedComponentNodeIterator_getNext(nodeIt)) != NULL) { - CuAssertTrue(testCase, stSet_search(test1, node) == NULL); - stSet_insert(test1, node); - } - stConnectedComponentNodeIterator_destruct(nodeIt); - CuAssertTrue(testCase, setsEqual(test1, truth1)); - stSet_destruct(truth1); - stSet_destruct(test1); - - stSet *truth2 = stSet_construct(); - stSet_insert(truth2, (void *) 5); - stSet_insert(truth2, (void *) 6); - stSet_insert(truth2, (void *) 7); - stSet *test2 = stSet_construct(); - stConnectedComponent *component2 = stConnectivity_getConnectedComponent(connectivity, (void *) 5); - nodeIt = stConnectedComponent_getNodeIterator(component2); - while ((node = stConnectedComponentNodeIterator_getNext(nodeIt)) != NULL) { - CuAssertTrue(testCase, stSet_search(test2, node) == NULL); - stSet_insert(test2, node); - } - stConnectedComponentNodeIterator_destruct(nodeIt); - CuAssertTrue(testCase, setsEqual(test2, truth2)); - stSet_destruct(truth2); - stSet_destruct(test2); - - stList_destruct(components); - teardown(); -} - -static void test_stConnectivity_removeNodesAndEdges(CuTest *testCase) { - setup(); - - stConnectivity_removeNode(connectivity, (void *) 6); - stConnectivity_removeEdge(connectivity, (void *) 1, (void *) 2); - stConnectivity_removeEdge(connectivity, (void *) 3, (void *) 1); - - stConnectedComponentIterator *componentIt = stConnectivity_getConnectedComponentIterator(connectivity); - stList *components = stList_construct(); - stConnectedComponent *component; - while ((component = stConnectedComponentIterator_getNext(componentIt)) != NULL) { - stList_append(components, component); - } - stConnectedComponentIterator_destruct(componentIt); - - CuAssertIntEquals(testCase, 4, stList_length(components)); - - stList_destruct(components); - - teardown(); -} -static void test_stConnectivity_connected(CuTest *testCase) { - setup(); - /* - * 1--2 - * | | - * 3--4 - * - * 5--6--7 - */ - - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 1, (void*) 3)); - CuAssertTrue(testCase, !stConnectivity_connected(connectivity, (void*) 3, (void*) 5)); - CuAssertTrue(testCase, !stConnectivity_connected(connectivity, (void*) 4, (void*) 7)); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 2, (void*) 4)); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 2, (void*) 3)); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 1, (void*) 2)); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 3, (void*) 4)); - - stConnectivity_removeEdge(connectivity, (void*) 5, (void*) 6); - CuAssertTrue(testCase, !stConnectivity_connected(connectivity, (void*) 5, (void*) 6)); - stConnectivity_removeEdge(connectivity, (void*) 1, (void*) 2); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 1, (void*) 3)); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 3, (void*) 4)); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 4, (void*) 2)); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 1, (void*) 2)); - - stConnectivity_removeEdge(connectivity, (void*) 2, (void*) 4); - CuAssertTrue(testCase, !stConnectivity_connected(connectivity, (void*) 1, (void*) 2)); - stConnectivity_addEdge(connectivity, (void*) 2, (void *) 4); - - stConnectivity_removeEdge(connectivity, (void*) 3, (void*)4); - CuAssertTrue(testCase, !stConnectivity_connected(connectivity, (void*) 1, (void*) 2)); - stConnectivity_addEdge(connectivity, (void*) 3, (void*) 4); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 3, (void*) 4)); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 1, (void*) 2)); - - - teardown(); - connectivity = stConnectivity_construct(); - stConnectivity_addNode(connectivity, (void*) 1); - stConnectivity_addNode(connectivity, (void*) 2); - stConnectivity_addNode(connectivity, (void*) 3); - stConnectivity_addNode(connectivity, (void*) 4); - stConnectivity_addEdge(connectivity, (void*) 1, (void*) 2); - stConnectivity_addEdge(connectivity, (void*) 1, (void*) 3); - stConnectivity_addEdge(connectivity, (void*) 1, (void*) 4); - - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*)1, (void*)3)); - stConnectivity_removeEdge(connectivity, (void*) 1, (void*) 4); - stConnectivity_removeEdge(connectivity, (void*) 1, (void*) 2); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*)1, (void*) 3)); - teardown(); -} -static void test_stConnectivity_nodeIterator(CuTest *testCase) { - setup(); - stConnectedComponent *comp = stConnectivity_getConnectedComponent(connectivity, (void*)4); - stConnectedComponentNodeIterator *it = stConnectedComponent_getNodeIterator(comp); - void *node; - stSet *nodesInComponent = stSet_construct(); - stSet *truth = stSet_construct(); - stSet_insert(truth, (void*)1); - stSet_insert(truth, (void*)2); - stSet_insert(truth, (void*)3); - stSet_insert(truth, (void*)4); - while((node = stConnectedComponentNodeIterator_getNext(it))) { - stSet_insert(nodesInComponent, node); - } - CuAssertTrue(testCase, setsEqual(nodesInComponent, truth)); - stSet_destruct(nodesInComponent); - stSet_destruct(truth); - stConnectedComponentNodeIterator_destruct(it); - - teardown(); -} -static void test_stConnectivity_compareWithNaive(CuTest *testCase) { - srand(time(NULL)); - int nNodes = 500; - int nEdgesToAdd = 800; - int nEdgesToRemove = 500; - int nQueries = 10000; - stList *nodes = stList_construct3(0, free); - stNaiveConnectivity *naive = stNaiveConnectivity_construct(); - connectivity = stConnectivity_construct(); - //add nodes - for (int i = 1; i <= nNodes; i++) { - int *node = malloc(sizeof(int)); - *node = i; - stNaiveConnectivity_addNode(naive, node); - stConnectivity_addNode(connectivity, node); - stList_append(nodes, node); - } - //add edges - while(nEdgesToAdd > 0) { - int *node1 = stList_get(nodes, rand() % nNodes); - int *node2 = stList_get(nodes, rand() % nNodes); - if(node1 >= node2) continue; - CuAssertTrue(testCase, stConnectivity_hasEdge(connectivity, node1, node2) == stNaiveConnectivity_hasEdge(naive, node1, node2)); - if(stConnectivity_hasEdge(connectivity, node1, node2)) continue; - stConnectivity_addEdge(connectivity, node1, node2); - stNaiveConnectivity_addEdge(naive, node1, node2); - nEdgesToAdd--; - } - //remove edges - while(nEdgesToRemove > 0) { - int *node1 = stList_get(nodes, rand() % nNodes); - int *node2 = stList_get(nodes, rand() % nNodes); - if(node1 >= node2) continue; - CuAssertTrue(testCase, stConnectivity_hasEdge(connectivity, node1, node2) == stNaiveConnectivity_hasEdge(naive, node1, node2)); - if(!stConnectivity_hasEdge(connectivity, node1, node2)) continue; - stConnectivity_removeEdge(connectivity, node1, node2); - stNaiveConnectivity_removeEdge(naive, node1, node2); - nEdgesToRemove--; - } - //check connectivity queries - while(nQueries > 0) { - int *node1 = stList_get(nodes, rand() % nNodes); - int *node2 = stList_get(nodes, rand() % nNodes); - if(node1 >= node2) continue; - stNaiveConnectedComponent *comp1 = stNaiveConnectivity_getConnectedComponent(naive, node1); - stNaiveConnectedComponent *comp2 = stNaiveConnectivity_getConnectedComponent(naive, node2); - bool naiveConnected = comp1 == comp2; - if(!naiveConnected == stConnectivity_connected(connectivity, node1, node2)) { - printf("%d and %d should be connected: %d\n", *node1, *node2, naiveConnected); - } - CuAssertTrue(testCase, naiveConnected == stConnectivity_connected(connectivity, node1, node2)); - nQueries--; - } - - - //check number of connected components - stList *components = stList_construct(); - stConnectedComponentIterator *it = stConnectivity_getConnectedComponentIterator(connectivity); - stConnectedComponent *comp; - while((comp = stConnectedComponentIterator_getNext(it))) { - stList_append(components, comp); - } - stConnectedComponentIterator_destruct(it); - - stList *trueComponents = stList_construct(); - stNaiveConnectedComponentIterator *itNaive = stNaiveConnectivity_getConnectedComponentIterator(naive); - stNaiveConnectedComponent *naiveComp; - while((naiveComp = stNaiveConnectedComponentIterator_getNext(itNaive))) { - stList_append(trueComponents, naiveComp); - } - stNaiveConnectedComponentIterator_destruct(itNaive); - CuAssertTrue(testCase, stList_length(components) == stList_length(trueComponents)); - //check the nodes in each component - for (int i = 0; i < stList_length(components); i++) { - stNaiveConnectedComponent *truecomponent_i = stList_get(trueComponents, i); - stSet *trueNodesInComponent = stNaiveConnectedComponent_getNodes(truecomponent_i); - stList *trueNodesInComponentList = stSet_getList(trueNodesInComponent); - void *nodeInComponent = stList_get(trueNodesInComponentList, 0); - stList_destruct(trueNodesInComponentList); - - stSet *nodesInComponent = stSet_construct(); - stConnectedComponent *comp_i = stConnectivity_getConnectedComponent(connectivity, nodeInComponent); - stConnectedComponentNodeIterator *nodeIt = - stConnectedComponent_getNodeIterator(comp_i); - void *node; - while((node = stConnectedComponentNodeIterator_getNext(nodeIt))) { - stSet_insert(nodesInComponent, node); - } - stConnectedComponentNodeIterator_destruct(nodeIt); - - CuAssertTrue(testCase, setsEqual(nodesInComponent, trueNodesInComponent)); - stSet_destruct(nodesInComponent); - } - stList_destruct(nodes); - stList_destruct(trueComponents); - stList_destruct(components); - stNaiveConnectivity_destruct(naive); - - teardown(); -} - -// Very simple test that multigraphs work properly. -static void test_stConnectivity_multigraphs(CuTest *testCase) { - setup(); - stConnectivity_addEdge(connectivity, (void*) 5, (void*) 6); - - stConnectivity_removeEdge(connectivity, (void*) 5, (void*) 6); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 5, (void*) 6)); - stConnectivity_removeEdge(connectivity, (void*) 5, (void*) 6); - CuAssertTrue(testCase, !stConnectivity_connected(connectivity, (void*) 5, (void*) 6)); - - stConnectivity_addEdge(connectivity, (void*) 5, (void*) 6); - stConnectivity_addEdge(connectivity, (void*) 5, (void*) 6); - CuAssertTrue(testCase, stConnectivity_connected(connectivity, (void*) 5, (void*) 7)); - stConnectivity_removeNode(connectivity, (void*) 6); - CuAssertTrue(testCase, !stConnectivity_connected(connectivity, (void*) 5, (void*) 7)); - - teardown(); -} - -// Test that components always get the same pointer unless those specific -// components have been modified. (Previously the API spec dictated that -// the components must be invalidated after any edge insertion or -// deletion). -static void test_stConnectivity_constantComponentPointers(CuTest *testCase) { - setup(); - - stConnectedComponent *component1 = stConnectivity_getConnectedComponent(connectivity, (void *) 2); - stConnectedComponent *component2 = stConnectivity_getConnectedComponent(connectivity, (void *) 5); - stConnectivity_addEdge(connectivity, (void *) 2, (void *) 3); // Doesn't affect components - - CuAssertTrue(testCase, component1 == stConnectivity_getConnectedComponent(connectivity, (void *) 2)); - CuAssertTrue(testCase, component2 == stConnectivity_getConnectedComponent(connectivity, (void *) 5)); - - stConnectivity_removeEdge(connectivity, (void *) 2, (void *) 3); // Doesn't affect components - - CuAssertTrue(testCase, component1 == stConnectivity_getConnectedComponent(connectivity, (void *) 2)); - CuAssertTrue(testCase, component2 == stConnectivity_getConnectedComponent(connectivity, (void *) 5)); - - teardown(); -} - -typedef enum { - CREATION, - DELETION, - MERGE, - CLEAVE -} componentCallback; - -componentCallback callbackResults[256]; - -int64_t curCallbackResultsIdx = 0; - -static void createCallback(void *ignored, stConnectedComponent *adjComponent) { - callbackResults[curCallbackResultsIdx++] = CREATION; -} - -static void deleteCallback(void *ignored, stConnectedComponent *adjComponent) { - callbackResults[curCallbackResultsIdx++] = DELETION; -} - -static void mergeCallback(void *ignored, stConnectedComponent *adjComponent1, stConnectedComponent *adjComponent2) { - callbackResults[curCallbackResultsIdx++] = MERGE; -} - -static void cleaveCallback(void *ignored, stConnectedComponent *adjComponent1, stConnectedComponent *adjComponent2, stSet *vertices) { - callbackResults[curCallbackResultsIdx++] = CLEAVE; -} - -static void test_stConnectivity_callbacks(CuTest *testCase) { - connectivity = stConnectivity_construct(); - - stConnectivity_setCreationCallback(connectivity, createCallback, NULL); - stConnectivity_setDeletionCallback(connectivity, deleteCallback, NULL); - stConnectivity_setMergeCallback(connectivity, mergeCallback, NULL); - stConnectivity_setCleaveCallback(connectivity, cleaveCallback, NULL); - - // Create 2 nodes - stConnectivity_addNode(connectivity, (void *) 1); - stConnectivity_addNode(connectivity, (void *) 2); - - // Merge - stConnectivity_addEdge(connectivity, (void *) 1, (void *) 2); - - // Cleave - stConnectivity_removeEdge(connectivity, (void *) 1, (void *) 2); - - // Delete - stConnectivity_removeNode(connectivity, (void *) 1); - - CuAssertIntEquals(testCase, 5, curCallbackResultsIdx); - - CuAssertTrue(testCase, callbackResults[0] == CREATION); - CuAssertTrue(testCase, callbackResults[1] == CREATION); - CuAssertTrue(testCase, callbackResults[2] == MERGE); - CuAssertTrue(testCase, callbackResults[3] == CLEAVE); - CuAssertTrue(testCase, callbackResults[4] == DELETION); - - teardown(); -} - -CuSuite *sonLib_stConnectivityTestSuite(void) { - CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stConnectivity_newNodeShouldGoInANewComponent); - SUITE_ADD_TEST(suite, test_stConnectivity_connectedComponents); - SUITE_ADD_TEST(suite, test_stConnectivity_removeNodesAndEdges); - SUITE_ADD_TEST(suite, test_stConnectivity_connected); - SUITE_ADD_TEST(suite, test_stConnectivity_nodeIterator); - SUITE_ADD_TEST(suite, test_stConnectivity_compareWithNaive); - SUITE_ADD_TEST(suite, test_stConnectivity_multigraphs); - SUITE_ADD_TEST(suite, test_stConnectivity_constantComponentPointers); - SUITE_ADD_TEST(suite, test_stConnectivity_callbacks); - return suite; -} - diff --git a/C/tests/sonLibDoubleTuplesTest.c b/C/tests/sonLibDoubleTuplesTest.c deleted file mode 100644 index 9e9a88c..0000000 --- a/C/tests/sonLibDoubleTuplesTest.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibContainersTest.c - * - * Created on: 26-May-2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsTest.h" - -static stDoubleTuple *doubleTuple1 = NULL; -static stDoubleTuple *doubleTuple2, *doubleTuple3, *doubleTuple4, *doubleTuple5; - -static void teardown() { - if(doubleTuple1 != NULL) { - stDoubleTuple_destruct(doubleTuple1); - stDoubleTuple_destruct(doubleTuple2); - stDoubleTuple_destruct(doubleTuple3); - stDoubleTuple_destruct(doubleTuple4); - stDoubleTuple_destruct(doubleTuple5); - doubleTuple1 = NULL; - } -} - -static void setup() { - teardown(); - doubleTuple1 = stDoubleTuple_construct(3, 1.0, 3.0, 2.0); - doubleTuple2 = stDoubleTuple_construct(4, 1.0, 5.0, 2.0, 7.0); - doubleTuple3 = stDoubleTuple_construct(0); - doubleTuple4 = stDoubleTuple_construct(3, 1.0, 3.0, 2.0); - doubleTuple5 = stDoubleTuple_construct(4, 1.0, 3.0, 2.0, 7.0); -} - -static void test_stDoubleTuple_construct(CuTest *testCase) { - assert(testCase != NULL); - setup(); //we don't do anything, this just checks that everything can construct and destruct okay. - teardown(); -} - -static void test_stDoubleTuple_hashKey(CuTest *testCase) { - setup(); - stHash *hash = stHash_construct3((uint64_t (*)(const void *))stDoubleTuple_hashKey, (int (*)(const void *, const void *))stDoubleTuple_equalsFn, NULL, NULL); - stHash_insert(hash, doubleTuple1, doubleTuple1); - stHash_insert(hash, doubleTuple2, doubleTuple2); - CuAssertTrue(testCase, stHash_search(hash, doubleTuple1) != NULL); - CuAssertTrue(testCase, stHash_search(hash, doubleTuple2) != NULL); - CuAssertTrue(testCase, stHash_search(hash, doubleTuple3) == NULL); - CuAssertTrue(testCase, stHash_search(hash, doubleTuple4) != NULL); - stHash_destruct(hash); - teardown(); -} - -static void test_stDoubleTuple_cmpFn(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple1, doubleTuple1) == 0); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple1, doubleTuple2) < 0); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple1, doubleTuple3) > 0); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple1, doubleTuple4) == 0); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple1, doubleTuple5) < 0); - - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple2, doubleTuple1) > 0); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple2, doubleTuple2) == 0); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple2, doubleTuple3) > 0); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple2, doubleTuple4) > 0); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple2, doubleTuple5) > 0); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple3, doubleTuple3) == 0); - teardown(); -} - -static void test_stDoubleTuple_equalsFn(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stDoubleTuple_equalsFn(doubleTuple1, doubleTuple1)); - CuAssertTrue(testCase, !stDoubleTuple_equalsFn(doubleTuple1, doubleTuple2)); - CuAssertTrue(testCase, !stDoubleTuple_equalsFn(doubleTuple1, doubleTuple3)); - CuAssertTrue(testCase, stDoubleTuple_equalsFn(doubleTuple1, doubleTuple4)); - CuAssertTrue(testCase, !stDoubleTuple_equalsFn(doubleTuple1, doubleTuple5)); - CuAssertTrue(testCase, stDoubleTuple_cmpFn(doubleTuple3, doubleTuple3) == 0); - teardown(); -} - -static void test_stDoubleTuple_length(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stDoubleTuple_length(doubleTuple1) == 3); - CuAssertTrue(testCase, stDoubleTuple_length(doubleTuple2) == 4); - CuAssertTrue(testCase, stDoubleTuple_length(doubleTuple3) == 0); - CuAssertTrue(testCase, stDoubleTuple_length(doubleTuple4) == 3); - CuAssertTrue(testCase, stDoubleTuple_length(doubleTuple5) == 4); - teardown(); -} - -static void test_stDoubleTuple_getPosition(CuTest *testCase) { - setup(); - CuAssertDblEquals(testCase, stDoubleTuple_getPosition(doubleTuple1, 0), 0.00000, 1); - CuAssertDblEquals(testCase, stDoubleTuple_getPosition(doubleTuple1, 1), 0.00000, 3); - CuAssertDblEquals(testCase, stDoubleTuple_getPosition(doubleTuple1, 2), 0.00000, 2); - stDoubleTuple *i = stDoubleTuple_construct(3, 0.3, 0.2, 1001.02); - CuAssertDblEquals(testCase, stDoubleTuple_getPosition(i, 0), 0.00000, 0.3); - CuAssertDblEquals(testCase, stDoubleTuple_getPosition(i, 1), 0.00000, 0.2); - CuAssertDblEquals(testCase, stDoubleTuple_getPosition(i, 2), 0.00000, 1001.02); - stDoubleTuple_destruct(i); - teardown(); -} - -CuSuite* sonLib_stDoubleTuplesTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stDoubleTuple_construct); - SUITE_ADD_TEST(suite, test_stDoubleTuple_hashKey); - SUITE_ADD_TEST(suite, test_stDoubleTuple_cmpFn); - SUITE_ADD_TEST(suite, test_stDoubleTuple_equalsFn); - SUITE_ADD_TEST(suite, test_stDoubleTuple_length); - SUITE_ADD_TEST(suite, test_stDoubleTuple_getPosition); - return suite; -} diff --git a/C/tests/sonLibEdgeContainerTests.c b/C/tests/sonLibEdgeContainerTests.c deleted file mode 100644 index dd9db8b..0000000 --- a/C/tests/sonLibEdgeContainerTests.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "sonLibGlobalsTest.h" -stEdgeContainer *container; -void destruct(char *v) { - free(v); -} -static void setup(void) { - container = stEdgeContainer_construct((void(*)(void*))destruct); - char *a = st_malloc(2); - strcpy(a, "a"); - char *b = st_malloc(2); - strcpy(b, "b"); - void *c = st_malloc(2); - strcpy(c, "c"); - - stEdgeContainer_addEdge(container, (void*)1, (void*)2, a); - stEdgeContainer_addEdge(container, (void*)1, (void*)3, b); - stEdgeContainer_addEdge(container, (void*)3, (void*)4, c); -} -static void teardown(void) { - stEdgeContainer_destruct(container); -} - -static void test_stEdgeContainer_getEdge(CuTest *testCase) { - setup(); - char *a = (char*)stEdgeContainer_getEdge(container, (void*)1, (void*)2); - CuAssertStrEquals(testCase, a, "a"); - char *b = (char*)stEdgeContainer_getEdge(container, (void*)1, (void*)3); - CuAssertStrEquals(testCase, b, "b"); - char *c = (char*)stEdgeContainer_getEdge(container, (void*)3, (void*)4); - CuAssertStrEquals(testCase, c, "c"); - - - teardown(); -} -static void test_stEdgeContainer_deletionOfThirdEdge(CuTest *testCase) { - container = stEdgeContainer_construct((void(*)(void*))destruct); - char *a = st_malloc(2); - strcpy(a, "a"); - char *b = st_malloc(2); - strcpy(b, "b"); - void *c = st_malloc(2); - strcpy(c, "c"); - stEdgeContainer_addEdge(container, (void*)1, (void*)2, a); - stEdgeContainer_addEdge(container, (void*)1, (void*)3, b); - stEdgeContainer_addEdge(container, (void*)1, (void*)4, c); - stEdgeContainer_deleteEdge(container, (void*)1, (void*)3); - stEdgeContainer_deleteEdge(container, (void*)1, (void*)4); - CuAssertTrue(testCase, stEdgeContainer_getEdge(container, (void*)1, (void*)2) != NULL); - teardown(); -} - - -static void test_stEdgeContainer_deleteEdge(CuTest *testCase) { - setup(); - stEdgeContainer_deleteEdge(container, (void*)1, (void*)2); - CuAssertTrue(testCase, !stEdgeContainer_getEdge(container, (void*)1, (void*)2)); - char *b = (char*)stEdgeContainer_getEdge(container, (void*)1, (void*)3); - CuAssertStrEquals(testCase, b, "b"); - teardown(); - setup(); - stEdgeContainer_deleteEdge(container, (void*)1, (void*)3); - CuAssertTrue(testCase, !stEdgeContainer_getEdge(container, (void*)1, (void*)3)); - char *a = (char*)stEdgeContainer_getEdge(container, (void*)1, (void*)2); - CuAssertStrEquals(testCase, a, "a"); - teardown(); -} -static void test_stEdgeContainer_iterator(CuTest *testCase) { - setup(); - stEdgeContainerIterator *it = stEdgeContainer_getIterator(container); - void *node1, *node2; - while(stEdgeContainer_getNext(it, &node1, &node2)) { - } - stEdgeContainer_destructIterator(it); - teardown(); -} - -CuSuite *sonLib_stEdgeContainerTestSuite(void) { - CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stEdgeContainer_getEdge); - SUITE_ADD_TEST(suite, test_stEdgeContainer_deleteEdge); - SUITE_ADD_TEST(suite, test_stEdgeContainer_deletionOfThirdEdge); - SUITE_ADD_TEST(suite, test_stEdgeContainer_iterator); - return suite; -} diff --git a/C/tests/sonLibEulerTest.c b/C/tests/sonLibEulerTest.c deleted file mode 100644 index dcfc06f..0000000 --- a/C/tests/sonLibEulerTest.c +++ /dev/null @@ -1,164 +0,0 @@ -#include "sonLibGlobalsTest.h" - -stEulerTour *et; - -static void setup(void) { - et = stEulerTour_construct(); - - stEulerTour_createVertex(et, (void*)1); - stEulerTour_createVertex(et, (void*)2); - stEulerTour_createVertex(et, (void*)3); - stEulerTour_createVertex(et, (void*)4); - stEulerTour_createVertex(et, (void*)5); - -} -static void teardown(void) { - stEulerTour_destruct(et); -} -static void test_stEulerTour_makeRoot(CuTest *testCase) { - setup(); - stEulerVertex *a = stEulerTour_getVertex(et, (void*)1); - stEulerVertex *b = stEulerTour_getVertex(et, (void*)2); - - - stEulerTour_link(et, (void*)1, (void*)2); - stEulerTour_makeRoot(et, a); - CuAssertTrue(testCase, stEulerTour_findRootNode(et, (void*)1) == (void*)1); - CuAssertTrue(testCase, stEulerTour_findRootNode(et, (void*)2) == (void*)1); - stEulerTour_makeRoot(et, b); - CuAssertTrue(testCase, stEulerTour_findRootNode(et, (void*)1) == (void*)2); - teardown(); -} - -static void test_stEulerTour_circle(CuTest *testCase) { - setup(); - stEulerVertex *c = stEulerTour_getVertex(et, (void*)3); - stEulerVertex *d = stEulerTour_getVertex(et, (void*)4); - stEulerTour_link(et, (void*)1, (void*)2); - stEulerTour_link(et, (void*)1, (void*)3); - stEulerTour_link(et, (void*)2, (void*)4); - stEulerTour_cut(et, (void*)1, (void*)2); - stEulerTour_makeRoot(et, c); - stEulerTour_makeRoot(et, d); - stEulerTour_link(et, (void*)3, (void*)4); - teardown(); -} - -static void test_stEulerTour_link(CuTest *testCase) { - setup(); - //stEulerVertex *a = stEulerTour_getVertex(et, (void*)1); - //stEulerVertex *b = stEulerTour_getVertex(et, (void*)2); - - - stEulerTour_link(et, (void*)1, (void*)2); - CuAssertTrue(testCase, stEulerTour_connected(et, (void*)1, (void*)2)); - - CuAssertTrue(testCase, !stEulerTour_connected(et, (void*)2, (void*)3)); - CuAssertTrue(testCase, !stEulerTour_connected(et, (void*)1, (void*)3)); - - /* - CuAssertTrue(testCase, a->leftOut->to == b); - CuAssertTrue(testCase, a->leftOut->from == a); - CuAssertTrue(testCase, b->rightIn->from == b); - CuAssertTrue(testCase, a->rightIn->to == a); - CuAssertTrue(testCase, stTreap_compare(a->leftOut->node, a->rightIn->node) < 0); - CuAssertTrue(testCase, stTreap_compare(a->leftOut->node, b->leftOut->node) == 0); - - CuAssertTrue(testCase, stTreap_next(a->leftOut->node) == b->rightIn->node); - */ - - CuAssertTrue(testCase, stEulerTour_findRootNode(et, (void*)1) == (void*)1); - CuAssertTrue(testCase, (char*)stEulerTour_findRootNode(et, (void*)2) == (void*)1); - - - /* - * d--a--b - * \ - * c - */ - - stEulerTour_link(et, (void*)1, (void*)3); - stEulerTour_link(et, (void*)2, (void*)4); - //CuAssertStrEquals(testCase, stEulerVertex_getTour(a), "dacaba"); - CuAssertTrue(testCase, stEulerTour_connected(et, (void*)4, (void*)2)); - - teardown(); -} -static bool setsEqual(stSet *set1, stSet *set2) { - stSet *diff = stSet_getDifference(set1, set2); - size_t size = stSet_size(diff); - stSet_destruct(diff); - return size == 0; -} - -static void test_stEulerTour_multipleIncidentEdges(CuTest *testCase) { - setup(); - stSet *trueNodes = stSet_construct(); - stEulerTour_link(et, (void*)1, (void*)2); - stEulerTour_link(et, (void*)1, (void*)3); - stEulerTour_link(et, (void*)1, (void*)4); - stSet_insert(trueNodes, (void*)1); - stSet_insert(trueNodes, (void*)2); - stSet_insert(trueNodes, (void*)3); - stSet_insert(trueNodes, (void*)4); - - stEulerTour_cut(et, (void*)1, (void*)2); - stSet_remove(trueNodes, (void*)2); - - CuAssertTrue(testCase, stEulerTour_connected(et, (void*)1, (void*)3)); - stSet *nodes = stEulerTour_getNodesInComponent(et, (void*)1); - CuAssertTrue(testCase, setsEqual(nodes, trueNodes)); - stEulerTour_cut(et, (void*)1, (void*)4); - - CuAssertTrue(testCase, stEulerTour_connected(et, (void*)1, (void*)3)); - stSet_destruct(nodes); - stSet_destruct(trueNodes); - teardown(); -} -static void test_stEulerTour_cut(CuTest *testCase) { - setup(); - stEulerTour_link(et, (void*)1, (void*)2); - stEulerTour_link(et, (void*)1, (void*)3); - stEulerTour_link(et, (void*)1, (void*)4); - stEulerTour_link(et, (void*)2, (void*)5); - stEulerTour_cut(et, (void*)1, (void*)2); - //CuAssertTrue(testCase, et->nComponents == 2); - CuAssertTrue(testCase, !stEulerTour_connected(et, (void*)1, (void*)2)); - stEulerTour_link(et, (void*)1, (void*)2); - CuAssertTrue(testCase, stEulerTour_connected(et, (void*)1, (void*)2)); - teardown(); -} -static void test_stEulerTour_next(CuTest *testCase) { - setup(); - /* - stEulerTour_link(et, (void*)1, (void*)2); - stEulerTour_link(et, (void*)1, (void*)3); - stEulerTour_link(et, (void*)1, (void*)4); - //stEulerTour_link(et, (void*)2, (void*)5); - stEulerTourIterator *it = stEulerTour_getIterator(et, (void*) 3); - void *node; - while((node = stEulerTourIterator_getNext(it))) { - printf("%p \n", node); - } - stEulerTourIterator_destruct(it); - stEulerTourEdgeIterator *edgeIt = stEulerTour_getEdgeIterator(et, (void*) 3); - stEulerHalfEdge *edge; - while((edge = stEulerTourEdgeIterator_getNext(edgeIt))) { - printf("%p->%p ", stEulerHalfEdge_getFrom(edge), stEulerHalfEdge_getTo(edge)); - } - stEulerTourEdgeIterator_destruct(edgeIt); - */ - teardown(); -} - - -CuSuite *sonLib_stEulerTestSuite(void) { - CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stEulerTour_link); - SUITE_ADD_TEST(suite, test_stEulerTour_cut); - SUITE_ADD_TEST(suite, test_stEulerTour_next); - SUITE_ADD_TEST(suite, test_stEulerTour_multipleIncidentEdges); - SUITE_ADD_TEST(suite, test_stEulerTour_circle); - SUITE_ADD_TEST(suite, test_stEulerTour_makeRoot); - return suite; -} diff --git a/C/tests/sonLibExceptTest.c b/C/tests/sonLibExceptTest.c deleted file mode 100644 index db00120..0000000 --- a/C/tests/sonLibExceptTest.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * basic tests of stExcept. - */ -#include "sonLibExcept.h" -#include "sonLibGlobalsTest.h" -#include "sonLibCommon.h" -#include -#include -#include "stSafeC.h" - -/* test throwing through two levels */ -static const char *const ERR1 = "err1"; -static const char *const ERR2 = "err2"; -static void thrower2() { - stThrowNew(ERR2, "error in %s", "thrower2"); -} - -static void thrower1(void) { - stTry { - thrower2(); - } stCatch(except) { - stThrow(stExcept_newCause(except, ERR1, "error in %s", "thrower1")); - } stTryEnd; -} - -static void testThrow(CuTest *testCase) { - volatile int gotEx = 0; - volatile int pastThrow = 0; - stTry { - thrower1(); - pastThrow++; - } stCatch(except) { - CuAssertTrue(testCase, stExcept_getId(except) == ERR1); - CuAssertTrue(testCase, stExcept_idEq(except, ERR1)); - CuAssertStrEquals(testCase, stExcept_getMsg(except), "error in thrower1"); - - const stExcept *cause = stExcept_getCause(except); - CuAssertTrue(testCase, cause != NULL); - if (cause != NULL) { - CuAssertTrue(testCase, stExcept_getId(cause) == ERR2); - CuAssertStrEquals(testCase, stExcept_getMsg(cause), "error in thrower2"); - CuAssertTrue(testCase, stExcept_getCause(cause) == NULL); - } - gotEx++; - } stTryEnd; - CuAssertTrue(testCase, pastThrow == 0); - CuAssertTrue(testCase, gotEx != 0); - CuAssertTrue(testCase, _cexceptTOS == NULL); -} - -/* test execution with no exception */ -static void noop(void) { -} - -static void testOk(CuTest *testCase) { - volatile int gotEx = 0; - volatile int pastOk = 0; - stTry { - noop(); - pastOk++; - } stCatch(except) { - stExcept_free(except); - gotEx++; - } stTryEnd; - CuAssertTrue(testCase, pastOk != 0); - CuAssertTrue(testCase, gotEx == 0); - CuAssertTrue(testCase, _cexceptTOS == NULL); -} - -/* test ceTryReturn */ -static int returnFromTry(void) { - stTry { - stTryReturn(10); - } stCatch(except) { - stExcept_free(except); - return 11; - } stTryEnd; - return 12; -} - -static int returnFromCatch(void) { - stTry { - stThrowNew(ERR1, "throw from catch"); - } stCatch(except) { - stExcept_free(except); - return 11; - } stTryEnd; - return 12; -} - -static int returnAtEnd(void) { - stTry { - } stCatch(except) { - stExcept_free(except); - return 11; - } stTryEnd; - return 12; -} - -static void testTryReturn(CuTest *testCase) { - int val = returnFromTry(); - CuAssertTrue(testCase, val == 10); - val = returnFromCatch(); - CuAssertTrue(testCase, val == 11); - val = returnAtEnd(); - CuAssertTrue(testCase, val == 12); -} - -#if 0 -// FIXME: finish this once there are some functions to read in all of a file - -/* Child process that throws an exception with no catch, redirecting stdout/stderr to - * the specified file. */ -static void noCatchChild(const char *errFile) { - fflush(stdout); - fflush(stderr); - int fn = open(errFile, O_WRONLY|O_CREAT|O_TRUNC, 0666); - if (fn < 0) { - st_errnoAbort("can't open: %s", errFile); - } - if (dup2(STDOUT_FILENO, fn) < 0) { - st_errnoAbort("dup stdout failed"); - } - if (dup2(STDERR_FILENO, fn) < 0) { - st_errnoAbort("dup stderr failed"); - } - thrower1(); - fprintf(stderr, "shouldn't make it past throw without catch\n"); - exit(1); -} - -/* test handling of a throw without a catch, which is must be run in a - * separate process */ -static void testNoCatch(CuTest *testCase) { - // FIXME: need function to get tmp file honoring TMPENV - char *errFile = "sonLibExceptTest.tmp"; - noCatchChild - - unlink(errFile); // ignore failures -} -#endif - -CuSuite* sonLib_stExceptTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, testThrow); - SUITE_ADD_TEST(suite, testOk); - SUITE_ADD_TEST(suite, testTryReturn); - return suite; -} - diff --git a/C/tests/sonLibFileTest.c b/C/tests/sonLibFileTest.c deleted file mode 100644 index 7c860cb..0000000 --- a/C/tests/sonLibFileTest.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "sonLibGlobalsTest.h" - -static char *tempFileDir = "sonLibFileTestTempDir"; -static char *tempFileName1 = - "sonLibFileTestTempDir/sonLibFileTestTempFile1.txt"; -static char *tempFileName2 = - "sonLibFileTestTempDir/sonLibFileTestTempFile2.txt"; - -static void teardown() { - if (stFile_exists(tempFileDir)) { - stFile_rmrf(tempFileDir); - } -} - -static void setup() { - teardown(); - - //Make the temp dir - stFile_mkdir(tempFileDir); - //Now the containing files - - //Temp file 1 - FILE *fileHandle = fopen(tempFileName1, "w"); - fprintf(fileHandle, "hello world\n"); - fprintf(fileHandle, "foo bar 123456\n"); - fprintf(fileHandle, " \n"); - fprintf(fileHandle, "\n"); - fprintf(fileHandle, "bye bye\n"); - fprintf(fileHandle, "\t"); - fclose(fileHandle); - - //Temp file 2 - fileHandle = fopen(tempFileName2, "w"); - fclose(fileHandle); -} - -static void test_stFile_getLineFromFile(CuTest *testCase) { - setup(); - FILE *fileHandle = fopen(tempFileName1, "r"); - char *s = stFile_getLineFromFile(fileHandle); - CuAssertStrEquals(testCase, "hello world", s); - free(s); - s = stFile_getLineFromFile(fileHandle); - CuAssertStrEquals(testCase, "foo bar 123456", s); - free(s); - s = stFile_getLineFromFile(fileHandle); - CuAssertStrEquals(testCase, " ", s); - free(s); - s = stFile_getLineFromFile(fileHandle); - CuAssertStrEquals(testCase, "", s); - free(s); - s = stFile_getLineFromFile(fileHandle); - CuAssertStrEquals(testCase, "bye bye", s); - free(s); - s = stFile_getLineFromFile(fileHandle); - CuAssertStrEquals(testCase, "\t", s); - free(s); - CuAssertTrue(testCase, NULL == stFile_getLineFromFile(fileHandle)); - CuAssertTrue(testCase, NULL == stFile_getLineFromFile(fileHandle)); - CuAssertTrue(testCase, NULL == stFile_getLineFromFile(fileHandle)); - CuAssertTrue(testCase, NULL == stFile_getLineFromFile(fileHandle)); - CuAssertTrue(testCase, NULL == stFile_getLineFromFile(fileHandle)); - fclose(fileHandle); - teardown(); -} - -static void test_stFile_exists(CuTest *testCase) { - teardown(); - CuAssertTrue(testCase, !stFile_exists(tempFileDir)); - CuAssertTrue(testCase, !stFile_exists(tempFileName1)); - CuAssertTrue(testCase, !stFile_exists(tempFileName2)); - setup(); - CuAssertTrue(testCase, stFile_exists(tempFileDir)); - CuAssertTrue(testCase, stFile_exists(tempFileName1)); - CuAssertTrue(testCase, stFile_exists(tempFileName2)); - teardown(); -} - -static void test_stFile_isDir(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stFile_isDir(tempFileDir)); - CuAssertTrue(testCase, !stFile_isDir(tempFileName1)); - CuAssertTrue(testCase, !stFile_isDir(tempFileName2)); - teardown(); - stTry { - stFile_isDir(tempFileDir); - CuAssertTrue(testCase, 0); - } - stCatch(except) - { - CuAssertStrEquals(testCase, stExcept_getId(except), - ST_FILE_EXCEPTION); - }stTryEnd; -} - -static void test_stFile_getFileNamesInDirectory(CuTest *testCase) { - setup(); - stList *childFiles = stFile_getFileNamesInDirectory(tempFileDir); - CuAssertIntEquals(testCase, stList_length(childFiles), 2); - char *file1 = stFile_pathJoin(tempFileDir, stList_get(childFiles, 0)); - char *file2 = stFile_pathJoin(tempFileDir, stList_get(childFiles, 1)); - CuAssertTrue(testCase, stString_eq(file1, tempFileName1) || stString_eq(file1, tempFileName2)); - CuAssertTrue(testCase, stString_eq(file2, tempFileName1) || stString_eq(file2, tempFileName2)); - CuAssertTrue(testCase, !stString_eq(file1, file2)); - stList_destruct(childFiles); - free(file1); - free(file2); - stTry { - stFile_getFileNamesInDirectory(tempFileName1); - CuAssertTrue(testCase, 0); - } - stCatch(except) - { - CuAssertStrEquals(testCase, stExcept_getId(except), - ST_FILE_EXCEPTION); - }stTryEnd; - teardown(); - stTry { - stFile_getFileNamesInDirectory(tempFileDir); - CuAssertTrue(testCase, 0); - } - stCatch(except) - { - CuAssertStrEquals(testCase, stExcept_getId(except), - ST_FILE_EXCEPTION); - }stTryEnd; -} - -static void test_stFile_pathJoin(CuTest *testCase) { - char *s = stFile_pathJoin("hello", "world"); - CuAssertStrEquals(testCase, "hello/world", s); - free(s); - s = stFile_pathJoin("hello/", "world"); - CuAssertStrEquals(testCase, "hello/world", s); - free(s); - s = stFile_pathJoin("", "world"); - CuAssertStrEquals(testCase, "world", s); - free(s); - s = stFile_pathJoin("hello", ""); - CuAssertStrEquals(testCase, "hello/", s); - free(s); - s = stFile_pathJoin("", ""); - CuAssertStrEquals(testCase, "", s); - free(s); -} - -CuSuite* sonLibFileTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stFile_getLineFromFile); - SUITE_ADD_TEST(suite, test_stFile_pathJoin); - SUITE_ADD_TEST(suite, test_stFile_exists); - SUITE_ADD_TEST(suite, test_stFile_isDir); - SUITE_ADD_TEST(suite, test_stFile_getFileNamesInDirectory); - - return suite; -} diff --git a/C/tests/sonLibGlobalsTest.h b/C/tests/sonLibGlobalsTest.h deleted file mode 100644 index ddb1293..0000000 --- a/C/tests/sonLibGlobalsTest.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibPrivate.h - * - * Created on: 21 May 2010 - * Author: benedictpaten - */ - -#ifndef SONLIB_GLOBALS_TEST_H_ -#define SONLIB_GLOBALS_TEST_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "CuTest.h" -#include "sonLib.h" - -#endif // SONLIB_GLOBALS_TEST_H_ diff --git a/C/tests/sonLibGraphTest.c b/C/tests/sonLibGraphTest.c deleted file mode 100644 index 0661941..0000000 --- a/C/tests/sonLibGraphTest.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "sonLibGlobalsTest.h" - -static const int64_t vertexNo = 7; -static stGraph *g = NULL; //Graph has vertices {0, 1, 2, 3, 4, 5, 6} - -static double e12W = 0.5; -static double e13W = 0.3; -static double e14W = 0.2; -static double e24W = 0.1; -static double e34W = 0.2; -static double e35W = 0.4; -static double e05W = 0.2; - -static void teardown() { - if (g != NULL) { - stGraph_destruct(g); - g = NULL; - } -} - -static void setup() { - teardown(); - g = stGraph_construct(vertexNo); - stGraph_addEdge(g, 1, 2, e12W); - stGraph_addEdge(g, 1, 3, e13W); - stGraph_addEdge(g, 1, 4, e14W); - stGraph_addEdge(g, 2, 4, e24W); - stGraph_addEdge(g, 3, 4, e34W); - stGraph_addEdge(g, 3, 5, e35W); - stGraph_addEdge(g, 0, 5, e05W); -} - -static void test_stGraph(CuTest *testCase) { - setup(); - CuAssertIntEquals(testCase, stGraph_cardinality(g), vertexNo); - stEdge *e = stGraph_getEdges(g, 0); - CuAssertIntEquals(testCase, 5, stEdge_to(e)); - CuAssertDblEquals(testCase, e05W, stEdge_weight(e), 0.0); - CuAssertPtrEquals(testCase, NULL, stEdge_nextEdge(e)); - e = stGraph_getEdges(g, 5); - CuAssertIntEquals(testCase, 0, stEdge_to(e)); - CuAssertDblEquals(testCase, e05W, stEdge_weight(e), 0.0); - e = stEdge_nextEdge(e); - CuAssertIntEquals(testCase, 3, stEdge_to(e)); - CuAssertDblEquals(testCase, e35W, stEdge_weight(e), 0.0); - CuAssertPtrEquals(testCase, NULL, stEdge_nextEdge(e)); - CuAssertPtrEquals(testCase, NULL, stGraph_getEdges(g, 6)); - teardown(); -} - -static void test_stGraph_shortestPaths(CuTest *testCase) { - setup(); - double *dist = stGraph_shortestPaths(g, 1); - double exDist[] = { 0.9, 0.0, 0.3, 0.3, 0.2, 0.7, INT64_MAX }; - for(int64_t v=0; v 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple1, intTuple4) == 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple1, intTuple5) < 0); - - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple1) > 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple2) == 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple3) > 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple4) > 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple5) > 0); - - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple3, intTuple3) == 0); - teardown(); -} - -static void test_stIntTuple_equalsFn(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stIntTuple_equalsFn(intTuple1, intTuple1)); - CuAssertTrue(testCase, !stIntTuple_equalsFn(intTuple1, intTuple2)); - CuAssertTrue(testCase, !stIntTuple_equalsFn(intTuple1, intTuple3)); - CuAssertTrue(testCase, stIntTuple_equalsFn(intTuple1, intTuple4)); - CuAssertTrue(testCase, !stIntTuple_equalsFn(intTuple1, intTuple5)); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple3, intTuple3) == 0); - teardown(); -} - -static void test_stIntTuple_length(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stIntTuple_length(intTuple1) == 3); - CuAssertTrue(testCase, stIntTuple_length(intTuple2) == 4); - CuAssertTrue(testCase, stIntTuple_length(intTuple3) == 0); - CuAssertTrue(testCase, stIntTuple_length(intTuple4) == 3); - CuAssertTrue(testCase, stIntTuple_length(intTuple5) == 4); - teardown(); -} - -static void test_stIntTuple_getPosition(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stIntTuple_get(intTuple1, 0) == 1); - CuAssertTrue(testCase, stIntTuple_get(intTuple1, 1) == 3); - CuAssertTrue(testCase, stIntTuple_get(intTuple1, 2) == 2); - teardown(); -} - -CuSuite* sonLib_stIntTuplesTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stIntTuple_construct); - SUITE_ADD_TEST(suite, test_stIntTuple_hashKey); - SUITE_ADD_TEST(suite, test_stIntTuple_cmpFn); - SUITE_ADD_TEST(suite, test_stIntTuple_equalsFn); - SUITE_ADD_TEST(suite, test_stIntTuple_length); - SUITE_ADD_TEST(suite, test_stIntTuple_getPosition); - return suite; -} diff --git a/C/tests/sonLibListTest.c b/C/tests/sonLibListTest.c deleted file mode 100644 index e4f20a6..0000000 --- a/C/tests/sonLibListTest.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibTest.c - * - * Created on: 24 May 2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsTest.h" - -static stList *list = NULL; -static int64_t stringNumber = 5; -static char *strings[5] = { "one", "two", "three", "four", "five" }; - -static void teardown() { - if(list != NULL) { - stList_destruct(list); - list = NULL; - } -} - -static void setup() { - teardown(); - list = stList_construct(); - int64_t i; - for(i=0; i=0; i--) { - CuAssertTrue(testCase, stList_pop(list) == strings[i]); - CuAssertTrue(testCase, stList_length(list) == i); - } - teardown(); -} - -void test_stList_remove(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stList_remove(list, 0) == strings[0]); - CuAssertTrue(testCase, stList_length(list) == stringNumber-1); - CuAssertTrue(testCase, stList_remove(list, 1) == strings[2]); - CuAssertTrue(testCase, stList_length(list) == stringNumber-2); - teardown(); -} - -void test_stList_removeItem(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stList_contains(list, strings[2])); - stList_removeItem(list, strings[2]); - CuAssertTrue(testCase, !stList_contains(list, strings[2])); - stList_removeItem(list, strings[2]); - CuAssertTrue(testCase, !stList_contains(list, strings[2])); - teardown(); -} - -void test_stList_removeFirst(CuTest *testCase) { - setup(); - int64_t i; - for(i=0; i 0) { - for(int64_t i=0; i 1); - for (uint64_t i = 0; i < n; ++i) { - sv += (array[i] - mu) * (array[i] - mu); - } - sv /= (n - 1); - return sv; -} -static double sv64(int64_t *array, uint64_t n, double mu) { - // sample variance. - double sv = 0.0; - assert(n > 1); - for (uint64_t i = 0; i < n; ++i) { - sv += (array[i] - mu) * (array[i] - mu); - } - sv /= (n - 1); - return sv; -} -static void test_st_randomInt(CuTest *testCase) { - /* - * Exercises the random int function. - */ - int64_t min = INT64_MIN; - int64_t max = INT64_MAX; - int64_t v; - for (int64_t i = -9; i < 10; ++i) { - CuAssertTrue(testCase, st_randomInt(i, i + 1) == i); - } - for(int64_t i = 0; i < 100000; i++) { - v = st_randomInt(min, max); - CuAssertTrue(testCase, v >= min); - CuAssertTrue(testCase, v < max); - } - min = -1; - max = 10; - for(int64_t i = 0; i < 100000; i++) { - v = st_randomInt(min, max); - CuAssertTrue(testCase, v >= min); - CuAssertTrue(testCase, v < max); - } - stTry { - st_randomInt(1, 1); - } stCatch(except) { - CuAssertTrue(testCase, stExcept_getId(except) == RANDOM_EXCEPTION_ID); - } stTryEnd -} -static void test_st_randomInt_distribution_0(CuTest *testCase) { - /* - * check the distribution of the randomInt function - */ - double med, var, mu = 0.0; - uint64_t n = 1000000; - uint64_t reps = 50; - int64_t min = 0; - int64_t max = 101; - int64_t *array = NULL; - for (uint64_t j = 0; j < reps; ++j) { - array = (int64_t *) st_malloc(sizeof(*array) * n); - for (int64_t i = 0; i < n; i++) { - array[i] = st_randomInt(min, max); - mu = runningMean32(mu, array[i], i); - } - var = sv32(array, n, mu); - med = median32(array, n); // median() will sort array - CuAssertTrue(testCase, array[0] <= array[n - 1]); - CuAssertTrue(testCase, array[0] < max); - CuAssertTrue(testCase, array[n - 1] < max); - // median of discrete uniform is - // median = (a + b) / 2 - CuAssertTrue(testCase, med == 50.0); - // mean of discrete uniform is - // mu = (a + b) / 2 - CuAssertTrue(testCase, mu > 0.9 * (max - 1) / 2.0); - CuAssertTrue(testCase, mu < 1.1 * (max - 1) / 2.0); - // variance of discrete uniform is - // var = ((b - a + 1)^2 - 1) / 12 - CuAssertTrue(testCase, var < 1.1 * (((max - min + 1) * (max - min + 1) - 1) / 12.0)); - CuAssertTrue(testCase, var > 0.9 * (((max - min + 1) * (max - min + 1) - 1) / 12.0)); - free(array); - } -} -static void test_st_randomInt64_range_0(CuTest *testCase) { - /* - * Excercies the randomInt64 function. - */ - int64_t min = INT64_MIN; - int64_t max = INT64_MAX; - int64_t v; - for (int64_t i = -9; i < 10; ++i) { - CuAssertTrue(testCase, st_randomInt64(i, i + 1) == i); - } - for (int64_t i = 0; i < 100000; i++) { - v = st_randomInt64(min, max); - CuAssertTrue(testCase, v >= min); - CuAssertTrue(testCase, v < max); - } - stTry { - st_randomInt64(1, 1); - } stCatch(except) { - CuAssertTrue(testCase, stExcept_getId(except) == RANDOM_EXCEPTION_ID); - } stTryEnd -} -static void test_st_randomInt64_distribution_0(CuTest *testCase) { - /* - * check the distribution of the randomInt64 function - */ - double med, var, mu = 0.0; - uint64_t n = 1000000; - uint64_t reps = 50; - int64_t min = 0; - int64_t max = 101; - int64_t *array = NULL; - for (uint64_t j = 0; j < reps; ++j) { - array = (int64_t *) st_malloc(sizeof(*array) * n); - for (int64_t i = 0; i < n; i++) { - array[i] = st_randomInt64(min, max); - mu = runningMean64(mu, array[i], i); - } - var = sv64(array, n, mu); - med = median64(array, n); // median() will sort array - CuAssertTrue(testCase, array[0] <= array[n - 1]); - CuAssertTrue(testCase, array[0] < max); - CuAssertTrue(testCase, array[n - 1] < max); - // median of discrete uniform is - // median = (a + b) / 2 - CuAssertTrue(testCase, med == 50.0); - // mean of discrete uniform is - // mu = (a + b) / 2 - CuAssertTrue(testCase, mu > 0.9 * (max - 1) / 2.0); - CuAssertTrue(testCase, mu < 1.1 * (max - 1) / 2.0); - // variance of discrete uniform is - // var = ((b - a + 1)^2 - 1) / 12 - CuAssertTrue(testCase, var < 1.1 * (((max - min + 1) * (max - min + 1) - 1) / 12.0)); - CuAssertTrue(testCase, var > 0.9 * (((max - min + 1) * (max - min + 1) - 1) / 12.0)); - free(array); - } -} -static void test_st_random(CuTest *testCase) { - /* - * Excercies the random int function. - */ - for(int64_t i = 0; i < 10000; i++) { - CuAssertTrue(testCase, st_random() >= 0); - CuAssertTrue(testCase, st_random() < 1.0); - } -} -static void test_st_randomChoice(CuTest *testCase) { - /* - * Excercies the random int function. - */ - stList *list = stList_construct3(0, (void (*)(void *))stIntTuple_destruct); - - stTry { - st_randomChoice(list); - } stCatch(except) { - CuAssertTrue(testCase, stExcept_getId(except) == RANDOM_EXCEPTION_ID); - } stTryEnd - - for(int64_t i = 0; i < 10; i++) { - stList_append(list, stIntTuple_construct1( i)); - } - for(int64_t i = 0; i < 100; i++) { - CuAssertTrue(testCase, stList_contains(list, st_randomChoice(list))); - } - stList_destruct(list); -} -CuSuite* sonLib_stRandomTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_st_randomInt); - SUITE_ADD_TEST(suite, test_st_randomInt_distribution_0); - SUITE_ADD_TEST(suite, test_st_randomInt64_range_0); - SUITE_ADD_TEST(suite, test_st_randomInt64_distribution_0); - SUITE_ADD_TEST(suite, test_st_random); - SUITE_ADD_TEST(suite, test_st_randomChoice); - return suite; -} diff --git a/C/tests/sonLibSetTest.c b/C/tests/sonLibSetTest.c deleted file mode 100644 index bf186d1..0000000 --- a/C/tests/sonLibSetTest.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright (C) 2012 by Dent Earl dentearl (a) gmail com - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "sonLibGlobalsTest.h" - -static stSet *set0, *set0Prime; -static stSet *set1; -static stIntTuple *one, *two, *three, *four, *five, *six; - -static void testSetup() { - // compare by value of memory address - set0 = stSet_construct(); - set0Prime = stSet_construct(); - // compare by value of ints. - set1 = stSet_construct3((uint64_t(*)(const void *)) stIntTuple_hashKey, - (int(*)(const void *, const void *)) stIntTuple_equalsFn, - (void(*)(void *)) stIntTuple_destruct); - one = stIntTuple_construct1( 0); - two = stIntTuple_construct1( 1); - three = stIntTuple_construct1( 2); - four = stIntTuple_construct1( 3); - five = stIntTuple_construct1( 4); - six = stIntTuple_construct1( 5); - stSet_insert(set0, one); - stSet_insert(set0, two); - stSet_insert(set0, three); - stSet_insert(set0, four); - stSet_insert(set0, five); - stSet_insert(set0, six); - stSet_insert(set0Prime, one); - stSet_insert(set0Prime, two); - stSet_insert(set0Prime, three); - stSet_insert(set0Prime, four); - stSet_insert(set0Prime, five); - stSet_insert(set0Prime, six); - stSet_insert(set1, one); - stSet_insert(set1, two); - stSet_insert(set1, three); - stSet_insert(set1, four); - stSet_insert(set1, five); - stSet_insert(set1, six); -} -static void testTeardown() { - stSet_destruct(set0); - stSet_destruct(set1); - stSet_destruct(set0Prime); -} -static void test_stSet_construct(CuTest* testCase) { - assert(testCase != NULL); - testSetup(); - /* Do nothing */ - testTeardown(); -} -static void test_stSet_search(CuTest* testCase) { - testSetup(); - stIntTuple *i = stIntTuple_construct1( 0); - stIntTuple *j = stIntTuple_construct2(10, 0); - stIntTuple *k = stIntTuple_construct1( 5); - //Check search by memory address - CuAssertTrue(testCase, stSet_search(set0, one) == one); - CuAssertTrue(testCase, stSet_search(set0, two) == two); - CuAssertTrue(testCase, stSet_search(set0, three) == three); - CuAssertTrue(testCase, stSet_search(set0, four) == four); - CuAssertTrue(testCase, stSet_search(set0, five) == five); - CuAssertTrue(testCase, stSet_search(set0, six) == six); - //Check not present - CuAssertTrue(testCase, stSet_search(set0, i) == NULL); - CuAssertTrue(testCase, stSet_search(set0, j) == NULL); - CuAssertTrue(testCase, stSet_search(set0, k) == NULL); - //Check search by memory address - CuAssertTrue(testCase, stSet_search(set1, one) == one); - CuAssertTrue(testCase, stSet_search(set1, two) == two); - CuAssertTrue(testCase, stSet_search(set1, three) == three); - CuAssertTrue(testCase, stSet_search(set1, four) == four); - CuAssertTrue(testCase, stSet_search(set1, five) == five); - CuAssertTrue(testCase, stSet_search(set1, six) == six); - //Check not present - CuAssertTrue(testCase, stSet_search(set1, j) == NULL); - //Check is searching by memory - CuAssertTrue(testCase, stSet_search(set1, i) == one); - CuAssertTrue(testCase, stSet_search(set1, k) == six); - stIntTuple_destruct(i); - stIntTuple_destruct(j); - stIntTuple_destruct(k); - testTeardown(); -} -static void test_stSet_remove(CuTest* testCase) { - testSetup(); - CuAssertTrue(testCase, stSet_remove(set0, one) == one); - CuAssertTrue(testCase, stSet_search(set0, one) == NULL); - CuAssertTrue(testCase, stSet_remove(set1, one) == one); - CuAssertTrue(testCase, stSet_search(set1, one) == NULL); - stSet_insert(set1, one); - CuAssertTrue(testCase, stSet_search(set1, one) == one); - testTeardown(); -} -static void test_stSet_removeAndFreeKey(CuTest* testCase) { - stSet *set2 = stSet_construct2(free); - stList *keys = stList_construct(); - int64_t keyNumber = 1000; - for (int64_t i = 0; i < keyNumber; i++) { - int64_t *key = st_malloc(sizeof(*key)); - stList_append(keys, key); - stSet_insert(set2, key); - } - for (int64_t i = 0; i < keyNumber; i++) { - int64_t *key = stList_get(keys, i); - CuAssertPtrEquals(testCase, key, stSet_removeAndFreeKey(set2, key)); - } - CuAssertIntEquals(testCase, 0, stSet_size(set2)); - stSet_destruct(set2); - stList_destruct(keys); -} -static void test_stSet_insert(CuTest* testCase) { - /* - * Tests inserting already present keys. - */ - testSetup(); - CuAssertTrue(testCase, stSet_search(set0, one) == one); - stSet_insert(set0, one); - CuAssertTrue(testCase, stSet_search(set0, one) == one); - stSet_insert(set0, three); - CuAssertTrue(testCase, stSet_search(set0, three) == three); - stIntTuple *seven = stIntTuple_construct2(7, 7); - CuAssertTrue(testCase, stSet_search(set0, seven) == NULL); - stSet_insert(set0, seven); - CuAssertTrue(testCase, stSet_search(set0, seven) == seven); - stIntTuple_destruct(seven); - testTeardown(); -} -static void test_stSet_size(CuTest *testCase) { - /* - * Tests the size function of the hash. - */ - testSetup(); - CuAssertTrue(testCase, stSet_size(set0) == 6); - CuAssertTrue(testCase, stSet_size(set1) == 6); - stSet *set2 = stSet_construct(); - CuAssertTrue(testCase, stSet_size(set2) == 0); - stSet_destruct(set2); - testTeardown(); -} -static void test_stSet_testIterator(CuTest *testCase) { - testSetup(); - stSetIterator *iterator = stSet_getIterator(set0); - stSetIterator *iteratorCopy = stSet_copyIterator(iterator); - int64_t i = 0; - stSet *seen = stSet_construct(); - for (i = 0; i < 6; i++) { - void *o = stSet_getNext(iterator); - CuAssertTrue(testCase, o != NULL); - CuAssertTrue(testCase, stSet_search(set0, o) != NULL); - CuAssertTrue(testCase, stSet_search(seen, o) == NULL); - CuAssertTrue(testCase, stSet_getNext(iteratorCopy) == o); - stSet_insert(seen, o); - } - CuAssertTrue(testCase, stSet_getNext(iterator) == NULL); - CuAssertTrue(testCase, stSet_getNext(iterator) == NULL); - CuAssertTrue(testCase, stSet_getNext(iteratorCopy) == NULL); - stSet_destruct(seen); - stSet_destructIterator(iterator); - stSet_destructIterator(iteratorCopy); - testTeardown(); -} -static void test_stSet_testGetKeys(CuTest *testCase) { - testSetup(); - stList *list = stSet_getKeys(set1); - CuAssertTrue(testCase, stList_length(list) == 6); - CuAssertTrue(testCase, stList_contains(list, one)); - CuAssertTrue(testCase, stList_contains(list, two)); - CuAssertTrue(testCase, stList_contains(list, three)); - CuAssertTrue(testCase, stList_contains(list, four)); - CuAssertTrue(testCase, stList_contains(list, five)); - CuAssertTrue(testCase, stList_contains(list, six)); - stList_destruct(list); - testTeardown(); -} -static void test_stSet_getUnion(CuTest* testCase) { - testSetup(); - // Check union of empty sets is empty - stSet *set2 = stSet_construct(); - stSet *set3 = stSet_construct(); - stSet *set4 = stSet_getUnion(set2, set3); - CuAssertTrue(testCase, stSet_size(set4) == 0); - stSet_destruct(set2); - stSet_destruct(set3); - stSet_destruct(set4); - // Check union of non empty set and empty set is non-empty - set2 = stSet_construct(); - set3 = stSet_getUnion(set0, set2); - CuAssertTrue(testCase, stSet_size(set3) == 6); - stSet_destruct(set2); - stSet_destruct(set3); - // Check union of two non-empty overlapping sets is correct - set2 = stSet_construct(); - set3 = stSet_construct(); - stIntTuple *uniqs[4]; - uniqs[0] = stIntTuple_construct2(9, 0); - uniqs[1] = stIntTuple_construct2(9, 1); - uniqs[2] = stIntTuple_construct2(9, 2); - uniqs[3] = stIntTuple_construct2(9, 3); - stIntTuple *common[5]; - common[0] = stIntTuple_construct2(5, 0); - common[1] = stIntTuple_construct2(5, 1); - common[2] = stIntTuple_construct2(5, 2); - common[3] = stIntTuple_construct2(5, 3); - common[4] = stIntTuple_construct2(5, 4); - for (int i = 0; i < 5; ++i) { - stSet_insert(set2, common[i]); - stSet_insert(set3, common[i]); - } - stSet_insert(set2, uniqs[0]); - stSet_insert(set2, uniqs[1]); - stSet_insert(set3, uniqs[2]); - stSet_insert(set3, uniqs[3]); - set4 = stSet_getUnion(set2, set3); - CuAssertTrue(testCase, stSet_size(set4) == 9); - for (int i = 0; i < 4; ++i) { - CuAssertTrue(testCase, stSet_search(set4, uniqs[i]) != NULL); - } - for (int i = 0; i < 5; ++i) { - CuAssertTrue(testCase, stSet_search(set4, common[i]) != NULL); - } - stSet_destruct(set2); - stSet_destruct(set3); - stSet_destruct(set4); - stIntTuple_destruct(common[0]); - stIntTuple_destruct(common[1]); - stIntTuple_destruct(common[2]); - stIntTuple_destruct(common[3]); - stIntTuple_destruct(common[4]); - stIntTuple_destruct(uniqs[0]); - stIntTuple_destruct(uniqs[1]); - stIntTuple_destruct(uniqs[2]); - stIntTuple_destruct(uniqs[3]); - // Check we get an exception with sets with different functions. - stTry { - stSet_getUnion(set0, set1); - } stCatch(except) { - CuAssertTrue(testCase, stExcept_getId(except) == SET_EXCEPTION_ID); - } stTryEnd - testTeardown(); -} -static void test_stSet_getIntersection(CuTest* testCase) { - testSetup(); - // Check intersection of empty sets is empty - stSet *set2 = stSet_construct(); - stSet *set3 = stSet_construct(); - stSet *set4 = stSet_getIntersection(set2, set3); - CuAssertTrue(testCase, stSet_size(set4) == 0); - stSet_destruct(set2); - stSet_destruct(set3); - stSet_destruct(set4); - // Check intersection of non empty set and empty set is empy - set2 = stSet_construct(); - set3 = stSet_getIntersection(set0, set2); - CuAssertTrue(testCase, stSet_size(set3) == 0); - stSet_destruct(set2); - stSet_destruct(set3); - // Check intersection of two non-empty overlapping sets is correct - set2 = stSet_construct(); - set3 = stSet_construct(); - stIntTuple *uniqs[4]; - uniqs[0] = stIntTuple_construct2(9, 0); - uniqs[1] = stIntTuple_construct2(9, 1); - uniqs[2] = stIntTuple_construct2(9, 2); - uniqs[3] = stIntTuple_construct2(9, 3); - stIntTuple *common[5]; - common[0] = stIntTuple_construct2(5, 0); - common[1] = stIntTuple_construct2(5, 1); - common[2] = stIntTuple_construct2(5, 2); - common[3] = stIntTuple_construct2(5, 3); - common[4] = stIntTuple_construct2(5, 4); - for (int i = 0; i < 5; ++i) { - stSet_insert(set2, common[i]); - stSet_insert(set3, common[i]); - } - stSet_insert(set2, uniqs[0]); - stSet_insert(set2, uniqs[1]); - stSet_insert(set3, uniqs[2]); - stSet_insert(set3, uniqs[3]); - set4 = stSet_getIntersection(set2, set3); - CuAssertTrue(testCase, stSet_size(set4) == 5); - stSetIterator *sit = stSet_getIterator(set4); - stIntTuple *itup; - while ((itup = stSet_getNext(sit)) != NULL) { - CuAssertTrue(testCase, stSet_search(set2, itup) != NULL); - CuAssertTrue(testCase, stSet_search(set3, itup) != NULL); - } - for (int i = 0; i < 4; ++i) { - CuAssertTrue(testCase, stSet_search(set4, uniqs[i]) == NULL); - } - stSet_destructIterator(sit); - stSet_destruct(set2); - stSet_destruct(set3); - stSet_destruct(set4); - stIntTuple_destruct(common[0]); - stIntTuple_destruct(common[1]); - stIntTuple_destruct(common[2]); - stIntTuple_destruct(common[3]); - stIntTuple_destruct(common[4]); - stIntTuple_destruct(uniqs[0]); - stIntTuple_destruct(uniqs[1]); - stIntTuple_destruct(uniqs[2]); - stIntTuple_destruct(uniqs[3]); - // Check we get an exception with sets with different functions. - stTry { - stSet_getIntersection(set0, set1); - } stCatch(except) { - CuAssertTrue(testCase, stExcept_getId(except) == SET_EXCEPTION_ID); - } stTryEnd - testTeardown(); -} -static void test_stSet_getDifference(CuTest* testCase) { - testSetup(); - // Check difference of empty sets is empty - stSet *set2 = stSet_construct(); - stSet *set3 = stSet_construct(); - stSet *set4 = stSet_getDifference(set2, set3); - CuAssertTrue(testCase, stSet_size(set4) == 0); - stSet_destruct(set2); - stSet_destruct(set3); - stSet_destruct(set4); - // Check difference of non empty set and empty set is non-empty - set2 = stSet_construct(); - set3 = stSet_getDifference(set0, set2); - CuAssertTrue(testCase, stSet_size(set3) == stSet_size(set0)); - stSet_destruct(set2); - stSet_destruct(set3); - set2 = stSet_construct(); - set3 = stSet_getDifference(set2, set0); - CuAssertTrue(testCase, stSet_size(set3) == 0); - stSet_destruct(set2); - stSet_destruct(set3); - // Check difference of two non-empty overlapping sets is correct - set2 = stSet_construct(); - set3 = stSet_construct(); - stIntTuple *uniqs[4]; - uniqs[0] = stIntTuple_construct2(9, 0); - uniqs[1] = stIntTuple_construct2(9, 1); - uniqs[2] = stIntTuple_construct2(9, 2); - uniqs[3] = stIntTuple_construct2(9, 3); - stIntTuple *common[5]; - common[0] = stIntTuple_construct2(5, 0); - common[1] = stIntTuple_construct2(5, 1); - common[2] = stIntTuple_construct2(5, 2); - common[3] = stIntTuple_construct2(5, 3); - common[4] = stIntTuple_construct2(5, 4); - for (int i = 0; i < 5; ++i) { - stSet_insert(set2, common[i]); - stSet_insert(set3, common[i]); - } - stSet_insert(set2, uniqs[0]); - stSet_insert(set2, uniqs[1]); - stSet_insert(set3, uniqs[2]); - stSet_insert(set3, uniqs[3]); - set4 = stSet_getDifference(set2, set3); - CuAssertTrue(testCase, stSet_size(set4) == 2); - for (int i = 0; i < 2; ++i) { - CuAssertTrue(testCase, stSet_search(set4, uniqs[i]) != NULL); - } - for (int i = 2; i < 4; ++i) { - CuAssertTrue(testCase, stSet_search(set4, uniqs[i]) == NULL); - } - for (int i = 2; i < 5; ++i) { - CuAssertTrue(testCase, stSet_search(set4, common[i]) == NULL); - } - stSet_destruct(set2); - stSet_destruct(set3); - stSet_destruct(set4); - stIntTuple_destruct(common[0]); - stIntTuple_destruct(common[1]); - stIntTuple_destruct(common[2]); - stIntTuple_destruct(common[3]); - stIntTuple_destruct(common[4]); - stIntTuple_destruct(uniqs[0]); - stIntTuple_destruct(uniqs[1]); - stIntTuple_destruct(uniqs[2]); - stIntTuple_destruct(uniqs[3]); - - // Check we get an exception with sets with different functions. - stTry { - stSet_getDifference(set0, set1); - } stCatch(except) { - CuAssertTrue(testCase, stExcept_getId(except) == SET_EXCEPTION_ID); - } stTryEnd - testTeardown(); -} - -static void test_stSet_peek(CuTest *testCase) { - /* - * Tests the peek function of the set. - */ - testSetup(); - CuAssertTrue(testCase, stSet_size(set0) == 6); - CuAssertTrue(testCase, stSet_search(set0, stSet_peek(set0)) != NULL); - CuAssertTrue(testCase, stSet_size(set1) == 6); - CuAssertTrue(testCase, stSet_search(set1, stSet_peek(set1)) != NULL); - stSet *set2 = stSet_construct(); - stTry { - stSet_peek(set2); - } stCatch(except) { - CuAssertTrue(testCase, stExcept_getId(except) == SET_EXCEPTION_ID); - } stTryEnd - stSet_destruct(set2); - testTeardown(); -} - -static void test_stSet_equals(CuTest *testCase) { - /* - * Tests the equals function of the set. - */ - testSetup(); - CuAssertTrue(testCase, stSet_equals(set0, set0)); - CuAssertTrue(testCase, stSet_equals(set0, set0Prime)); - stSet *set2 = stSet_construct(); - CuAssertTrue(testCase, !stSet_equals(set0, set2)); - CuAssertTrue(testCase, !stSet_equals(set0Prime, set2)); - stSet_destruct(set2); - testTeardown(); -} - -static void test_stSet_isSubset(CuTest *testCase) { - /* - * Tests the subset function of the set. - */ - testSetup(); - CuAssertTrue(testCase, stSet_isSubset(set0, set0)); - CuAssertTrue(testCase, stSet_isSubset(set0, set0Prime)); - stSet *set2 = stSet_construct(); - CuAssertTrue(testCase, stSet_isSubset(set0, set2)); - CuAssertTrue(testCase, !stSet_isSubset(set2, set0)); - stSet_destruct(set2); - testTeardown(); -} - -CuSuite* sonLib_stSetTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stSet_search); - SUITE_ADD_TEST(suite, test_stSet_remove); - SUITE_ADD_TEST(suite, test_stSet_removeAndFreeKey); - SUITE_ADD_TEST(suite, test_stSet_insert); - SUITE_ADD_TEST(suite, test_stSet_size); - SUITE_ADD_TEST(suite, test_stSet_testIterator); - SUITE_ADD_TEST(suite, test_stSet_construct); - SUITE_ADD_TEST(suite, test_stSet_testGetKeys); - SUITE_ADD_TEST(suite, test_stSet_getUnion); - SUITE_ADD_TEST(suite, test_stSet_getIntersection); - SUITE_ADD_TEST(suite, test_stSet_getDifference); - SUITE_ADD_TEST(suite, test_stSet_peek); - SUITE_ADD_TEST(suite, test_stSet_equals); - SUITE_ADD_TEST(suite, test_stSet_isSubset); - return suite; -} diff --git a/C/tests/sonLibSortedSetTest.c b/C/tests/sonLibSortedSetTest.c deleted file mode 100644 index b0655a7..0000000 --- a/C/tests/sonLibSortedSetTest.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -#include "sonLibGlobalsTest.h" - -static stSortedSet *sortedSet = NULL; -static stSortedSet *sortedSet2 = NULL; -static int64_t size = 7; -static int64_t input[] = { 1, 5, -1, 10, 12, 3, -10 }; -static int64_t sortedInput[] = { -10, -1, 1, 3, 5, 10, 12 }; -static int64_t sortedSize = 7; - - -static void sonLibSortedSetTestTeardown() { - if(sortedSet != NULL) { - stSortedSet_destruct(sortedSet); - stSortedSet_destruct(sortedSet2); - sortedSet = NULL; - } -} - -static void sonLibSortedSetTestSetup() { - sonLibSortedSetTestTeardown(); - sortedSet = stSortedSet_construct3((int (*)(const void *, const void *))stIntTuple_cmpFn, - (void (*)(void *))stIntTuple_destruct); - sortedSet2 = stSortedSet_construct3((int (*)(const void *, const void *))stIntTuple_cmpFn, - (void (*)(void *))stIntTuple_destruct); -} - -static void test_stSortedSet_construct(CuTest* testCase) { - sonLibSortedSetTestSetup(); - CuAssertTrue(testCase, sortedSet != NULL); - sonLibSortedSetTestTeardown(); -} - -static void test_stSortedSet_copyConstruct(CuTest* testCase) { - sonLibSortedSetTestSetup(); - CuAssertTrue(testCase, sortedSet != NULL); - int64_t i; - for(i=0; icount == 7); - - char *tour = stTreap_print(t); - CuAssertStrEquals(testCase, tour, "tabcdef"); - free(tour); - - /* - char *reverseTour = stTreap_printBackwards(t); - CuAssertStrEquals(testCase, reverseTour, "fedcbat"); - free(reverseTour); - */ - - stTreap *temp = stTreap_next(t); - CuAssertTrue(testCase, stTreap_compare(t, temp) < 0); - CuAssertTrue(testCase, stTreap_compare(temp, t) > 0); - - stTreap *node = stTreap_findMax(stTreap_findRoot(t)); - CuAssertStrEquals(testCase, node->value, "f"); - while(stTreap_prev(node)) { - node = stTreap_prev(node); - } - CuAssertTrue(testCase, node == t); - - teardown(); -} -static void test_stTreap_rotations(CuTest *testCase) { - setup(); - stTreap *r = stTreap_findRoot(t); - stTreap_rotateLeft(r); - stTreap *newRoot = stTreap_findRoot(t); - CuAssertTrue(testCase, newRoot->left == r); - CuAssertTrue(testCase, newRoot->count == 7); - - char *newTour = stTreap_print(t); - CuAssertStrEquals(testCase, newTour, "tabcdef"); - free(newTour); - - stTreap_rotateRight(newRoot); - CuAssertTrue(testCase, stTreap_findRoot(t) == r); - char *rotatedTour = stTreap_print(t); - CuAssertStrEquals(testCase, rotatedTour, "tabcdef"); - free(rotatedTour); - - - teardown(); -} -static void test_stTreap_split(CuTest *testCase) { - setup(); - stTreap *splitPoint = stTreap_next(t); - splitPoint = stTreap_next(splitPoint); - CuAssertStrEquals(testCase, splitPoint->value, "b"); - - - stTreap *beforeSplit = stTreap_splitBefore(splitPoint); - - char *beforeSplitStr = stTreap_print(beforeSplit); - char *splitPointStr = stTreap_print(splitPoint); - CuAssertStrEquals(testCase, beforeSplitStr, "ta"); - CuAssertStrEquals(testCase, splitPointStr, "bcdef"); - free(beforeSplitStr); - free(splitPointStr); - - stTreap_concat(beforeSplit, splitPoint); - char *recombinedTourStr = stTreap_print(t); - CuAssertStrEquals(testCase, recombinedTourStr, "tabcdef"); - free(recombinedTourStr); - - stTreap *endNode = stTreap_findMax(stTreap_findRoot(t)); - CuAssertStrEquals(testCase, endNode->value, "f"); - char *reverseTourStr = stTreap_printBackwards(endNode); - CuAssertStrEquals(testCase, reverseTourStr, "fedcbat"); - free(reverseTourStr); - - - stTreap *aftersplit = stTreap_next(t); - CuAssertStrEquals(testCase, aftersplit->value, "a"); - stTreap *after = stTreap_splitAfter(aftersplit); - CuAssertTrue(testCase, after != NULL); - char *afterSplitStr = stTreap_print(after); - CuAssertStrEquals(testCase, afterSplitStr, "bcdef"); - free(afterSplitStr); - stTreap_destruct(after); - - - teardown(); -} -static void test_stTreap_heapProperty(CuTest *testCase) { - setup(); - - - stTreap *iter = t; - while(iter) { - if(iter->parent) CuAssertTrue(testCase, iter->parent->priority > iter->priority); - iter = stTreap_next(iter); - } - - teardown(); -} - -CuSuite *sonLib_stTreapTestSuite(void) { - CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stTreap_ordering); - SUITE_ADD_TEST(suite, test_stTreap_rotations); - SUITE_ADD_TEST(suite, test_stTreap_split); - SUITE_ADD_TEST(suite, test_stTreap_heapProperty); - return suite; -} - diff --git a/C/tests/sonLibTreeTest.c b/C/tests/sonLibTreeTest.c deleted file mode 100644 index a5a3d64..0000000 --- a/C/tests/sonLibTreeTest.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * eTreeTest.c - * - * Created on: 21 May 2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsTest.h" - -static stTree *root = NULL; -static stTree *internal; -static stTree *child1; -static stTree *child2; - -static void teardown() { - if(root != NULL) { - stTree_destruct(root); - } - root = NULL; -} - -static void setup() { - root = stTree_construct(); - internal = stTree_construct(); - child1 = stTree_construct(); - child2 = stTree_construct(); - stTree_setParent(internal, root); - stTree_setParent(child1, internal); - stTree_setParent(child2, internal); - stTree_setLabel(root, "ROOT"); - stTree_setLabel(child1, "CHILD1"); - stTree_setBranchLength(child1, 1.1); - stTree_setBranchLength(internal, 0.5); -} - -static void test_stTree_construct(CuTest* testCase) { - setup(); - //tested by setup and teardown. - CuAssertTrue(testCase, root != NULL); - teardown(); -} - -static void test_stTree_getSetParent(CuTest* testCase) { - setup(); - CuAssertTrue(testCase, stTree_getParent(child1) == internal); - CuAssertTrue(testCase, stTree_getParent(child1) == internal); - CuAssertTrue(testCase, stTree_getParent(internal) == root); - CuAssertTrue(testCase, stTree_getParent(root) == NULL); - stTree_setParent(child1, NULL); - CuAssertTrue(testCase, stTree_getParent(child1) == NULL); - stTree_destruct(child1); - teardown(); -} - -static void test_stTree_getChildNumber(CuTest* testCase) { - setup(); - CuAssertTrue(testCase, stTree_getChildNumber(child1) == 0); - CuAssertTrue(testCase, stTree_getChildNumber(child1) == 0); - CuAssertTrue(testCase, stTree_getChildNumber(internal) == 2); - CuAssertTrue(testCase, stTree_getChildNumber(root) == 1); - stTree_setParent(child1, NULL); - CuAssertTrue(testCase, stTree_getChildNumber(internal) == 1); - stTree_destruct(child1); - teardown(); -} - -static void test_stTree_getChild(CuTest* testCase) { - setup(); - CuAssertTrue(testCase, stTree_getChild(internal, 0) == child1); - CuAssertTrue(testCase, stTree_getChild(internal, 1) == child2); - CuAssertTrue(testCase, stTree_getChild(root, 0) == internal); - stTree_setParent(child1, NULL); - CuAssertTrue(testCase, stTree_getChild(internal, 0) == child2); - stTree_setParent(child2, NULL); - CuAssertTrue(testCase, stTree_getChildNumber(internal) == 0); - stTree_setParent(child1, internal); - CuAssertTrue(testCase, stTree_getChild(internal, 0) == child1); - stTree_setParent(child2, internal); - CuAssertTrue(testCase, stTree_getChild(internal, 0) == child1); - CuAssertTrue(testCase, stTree_getChild(internal, 1) == child2); - teardown(); -} - -static void test_stTree_getSetBranchLength(CuTest* testCase) { - setup(); - CuAssertTrue(testCase, stTree_getBranchLength(child1) == 1.1); - CuAssertTrue(testCase, stTree_getBranchLength(child2) == INFINITY); - CuAssertTrue(testCase, stTree_getBranchLength(internal) == 0.5); - CuAssertTrue(testCase, stTree_getBranchLength(root) == INFINITY); - stTree_setBranchLength(child1, 1.3); - CuAssertTrue(testCase, stTree_getBranchLength(child1) == 1.3); - teardown(); -} - -static void test_stTree_getSetClientData(CuTest* testCase) { - setup(); - int data = 1010; - CuAssertTrue(testCase, stTree_getClientData(child1) == NULL); - stTree_setClientData(child1, &data); - CuAssertTrue(testCase, stTree_getClientData(child1) == &data); - teardown(); -} - -static void test_stTree_label(CuTest* testCase) { - setup(); - CuAssertStrEquals(testCase, "CHILD1", stTree_getLabel(child1)); - CuAssertTrue(testCase, stTree_getLabel(child2) == NULL); - CuAssertTrue(testCase, stTree_getLabel(internal) == NULL); - CuAssertStrEquals(testCase, "ROOT", stTree_getLabel(root)); - CuAssertTrue(testCase, stTree_findChild(root, "CHILD1") == child1); - CuAssertTrue(testCase, stTree_findChild(root, "CHILD100") == NULL); - stTree_setLabel(child1, "BOO"); - CuAssertStrEquals(testCase, "BOO", stTree_getLabel(child1)); - stTree_setLabel(child1, NULL); - CuAssertTrue(testCase, stTree_getLabel(child1) == NULL); - teardown(); -} - -static void test_stTree_newickTreeParser(CuTest *testCase) { - setup(); - char *testNewickStrings[4] = { "(((a,b,(c,))d),e)f;", ";", "f;", "();" }; - int64_t i; - for(i=0; i<4; i++) { - stTree *eTree2 = stTree_parseNewickString(testNewickStrings[i]); - CuAssertTrue(testCase, eTree2 != NULL); - char *newString = stTree_getNewickTreeString(eTree2); - CuAssertStrEquals(testCase, testNewickStrings[i], newString); - free(newString); - stTree_destruct(eTree2); - } - teardown(); -} - -static void test_stTree_getNumNodes(CuTest* testCase) { - setup(); - CuAssertTrue(testCase, stTree_getNumNodes(root) == 4); - teardown(); -} - -static void test_stTree_equals(CuTest* testCase) { - setup(); - stTree *root0 = root; - setup(); - CuAssertTrue(testCase, stTree_equals(root, root0)); - - stTree_setLabel(internal, "INTERNAL"); - CuAssertTrue(testCase, !stTree_equals(root, root0)); - - teardown(); - setup(); - stTree_setBranchLength(internal, 1.01); - CuAssertTrue(testCase, !stTree_equals(root, root0)); - - teardown(); - setup(); - stTree_setParent(stTree_construct(), internal); - CuAssertTrue(testCase, !stTree_equals(root, root0)); - - stTree_destruct(root0); - teardown(); -} - -static void test_stTree_clone(CuTest* testCase) { - setup(); - int data = 1010; - stTree_setClientData(child1, &data); - stTree *root2 = stTree_clone(root); - CuAssertTrue(testCase, stTree_equals(root, root2)); - CuAssertTrue(testCase, (stTree_getClientData(stTree_findChild(root2, "CHILD1")) == &data)); - stTree_destruct(root2); - teardown(); -} - -static int cmpByLabel(stTree *a, stTree *b) { - return strcmp(stTree_getLabel(a), stTree_getLabel(b)); -} - -void test_stTree_reRoot(CuTest *testCase) { - setup(); - // Re-rooting a tree at its existing root just returns a cloned - // tree - stTree *reRooted = stTree_reRoot(root, 0.0); - CuAssertTrue(testCase, stTree_equals(reRooted, root)); - stTree_destruct(reRooted); - - // Root the tree 0.1 units above the "internal" node. Since the - // root has no other children, this means the tree looks almost - // exactly the same, except that the root is closer. - reRooted = stTree_reRoot(internal, 0.1); - CuAssertTrue(testCase, stTree_getChildNumber(reRooted) == 1); - stTree *newInternal = stTree_getChild(reRooted, 0); - CuAssertTrue(testCase, stTree_getChildNumber(newInternal) == 2); - CuAssertTrue(testCase, stTree_getBranchLength(newInternal) == 0.1); - stTree_destruct(reRooted); - teardown(); - - // A slightly more complex example - stTree *tree = stTree_parseNewickString("((C:1,D:1)B:2,(F:3,G:3,(I:3,(K:4)J:5)H:5)E:6)A:9;"); - - reRooted = stTree_reRoot(stTree_findChild(tree, "J"), 1); - // Sort so that the newick string is consistent - stTree_sortChildren(reRooted, cmpByLabel); - char *s = stTree_getNewickTreeString(reRooted); - CuAssertStrEquals(testCase, "((((C:1,D:1)B:8,F:3,G:3)E:5,I:3)H:4,(K:4)J:1);", s); - free(s); - stTree_destruct(reRooted); - - // Rerooting at a different place above E should just shuffle B and E's branch lengths - reRooted = stTree_reRoot(stTree_findChild(tree, "E"), 2); - // Sort so that the newick string is consistent - stTree_sortChildren(reRooted, cmpByLabel); - s = stTree_getNewickTreeString(reRooted); - CuAssertStrEquals(testCase, "((C:1,D:1)B:6,(F:3,G:3,(I:3,(K:4)J:5)H:5)E:2);", s); - free(s); - stTree_destruct(reRooted); - - // Test rerooting on a leaf of a 3-child node - reRooted = stTree_reRoot(stTree_findChild(tree, "G"), 2); - // Sort so that the newick string is consistent - stTree_sortChildren(reRooted, cmpByLabel); - s = stTree_getNewickTreeString(reRooted); - CuAssertStrEquals(testCase, "(((C:1,D:1)B:8,F:3,(I:3,(K:4)J:5)H:5)E:1,G:2);", s); - free(s); - stTree_destruct(reRooted); - stTree_destruct(tree); - - // Test a multifurcating example that was broken - tree = stTree_parseNewickString("(8,(10,(1,11),(2,4,7)),(6,(0,5)),(3,9));"); - reRooted = stTree_reRoot(stTree_findChild(tree, "10"), 0.0); - s = stTree_getNewickTreeString(reRooted); - CuAssertStrEquals(testCase, "(10:0,((1,11),(2,4,7),(8,(6,(0,5)),(3,9))));", s); - free(s); - stTree_destruct(reRooted); - stTree_destruct(tree); -} - -static void test_stTree_getMRCA(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stTree_getMRCA(internal, internal) == internal); - CuAssertTrue(testCase, stTree_getMRCA(root, internal) == root); - CuAssertTrue(testCase, stTree_getMRCA(root, child1) == root); - CuAssertTrue(testCase, stTree_getMRCA(child2, root) == root); - CuAssertTrue(testCase, stTree_getMRCA(child2, child1) == internal); - teardown(); -} - -CuSuite* sonLib_ETreeTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stTree_construct); - SUITE_ADD_TEST(suite, test_stTree_getSetParent); - SUITE_ADD_TEST(suite, test_stTree_getChildNumber); - SUITE_ADD_TEST(suite, test_stTree_getChild); - SUITE_ADD_TEST(suite, test_stTree_getSetBranchLength); - SUITE_ADD_TEST(suite, test_stTree_getSetClientData); - SUITE_ADD_TEST(suite, test_stTree_newickTreeParser); - SUITE_ADD_TEST(suite, test_stTree_label); - SUITE_ADD_TEST(suite, test_stTree_getNumNodes); - SUITE_ADD_TEST(suite, test_stTree_equals); - SUITE_ADD_TEST(suite, test_stTree_clone); - SUITE_ADD_TEST(suite, test_stTree_reRoot); - SUITE_ADD_TEST(suite, test_stTree_getMRCA); - return suite; -} diff --git a/C/tests/sonLibTuplesTest.c b/C/tests/sonLibTuplesTest.c deleted file mode 100644 index 677ff96..0000000 --- a/C/tests/sonLibTuplesTest.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibContainersTest.c - * - * Created on: 26-May-2010 - * Author: benedictpaten - */ - -#include "sonLibGlobalsTest.h" - -static stIntTuple *intTuple1 = NULL; -static stIntTuple *intTuple2, *intTuple3, *intTuple4, *intTuple5; - -static void teardown() { - if(intTuple1 != NULL) { - stIntTuple_destruct(intTuple1); - stIntTuple_destruct(intTuple2); - stIntTuple_destruct(intTuple3); - stIntTuple_destruct(intTuple4); - stIntTuple_destruct(intTuple5); - intTuple1 = NULL; - } -} - -static void setup() { - teardown(); - intTuple1 = stIntTuple_construct3( 1, 3, 2); - intTuple2 = stIntTuple_construct4( 1, 5, 2, 7); - intTuple3 = stIntTuple_construct0(); - intTuple4 = stIntTuple_construct3( 1, 3, 2); - intTuple5 = stIntTuple_construct4( 1, 3, 2, 7); -} - -static void test_stIntTuple_construct(CuTest *testCase) { - assert(testCase != NULL); - setup(); //we don't do anything, this just checks that everything can construct and destruct okay. - teardown(); -} - -static void test_stIntTuple_hashKey(CuTest *testCase) { - setup(); - stHash *hash = stHash_construct3((uint64_t (*)(const void *))stIntTuple_hashKey, (int (*)(const void *, const void *))stIntTuple_equalsFn, NULL, NULL); - stHash_insert(hash, intTuple1, intTuple1); - stHash_insert(hash, intTuple2, intTuple2); - CuAssertTrue(testCase, stHash_search(hash, intTuple1) != NULL); - CuAssertTrue(testCase, stHash_search(hash, intTuple2) != NULL); - CuAssertTrue(testCase, stHash_search(hash, intTuple3) == NULL); - CuAssertTrue(testCase, stHash_search(hash, intTuple4) != NULL); - stHash_destruct(hash); - teardown(); -} - -static void test_stIntTuple_cmpFn(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple1, intTuple1) == 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple1, intTuple2) < 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple1, intTuple3) > 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple1, intTuple4) == 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple1, intTuple5) < 0); - - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple1) > 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple2) == 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple3) > 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple4) > 0); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple2, intTuple5) > 0); - - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple3, intTuple3) == 0); - teardown(); -} - -static void test_stIntTuple_equalsFn(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stIntTuple_equalsFn(intTuple1, intTuple1)); - CuAssertTrue(testCase, !stIntTuple_equalsFn(intTuple1, intTuple2)); - CuAssertTrue(testCase, !stIntTuple_equalsFn(intTuple1, intTuple3)); - CuAssertTrue(testCase, stIntTuple_equalsFn(intTuple1, intTuple4)); - CuAssertTrue(testCase, !stIntTuple_equalsFn(intTuple1, intTuple5)); - CuAssertTrue(testCase, stIntTuple_cmpFn(intTuple3, intTuple3) == 0); - teardown(); -} - -static void test_stIntTuple_length(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stIntTuple_length(intTuple1) == 3); - CuAssertTrue(testCase, stIntTuple_length(intTuple2) == 4); - CuAssertTrue(testCase, stIntTuple_length(intTuple3) == 0); - CuAssertTrue(testCase, stIntTuple_length(intTuple4) == 3); - CuAssertTrue(testCase, stIntTuple_length(intTuple5) == 4); - teardown(); -} - -static void test_stIntTuple_getPosition(CuTest *testCase) { - setup(); - CuAssertTrue(testCase, stIntTuple_get(intTuple1, 0) == 1); - CuAssertTrue(testCase, stIntTuple_get(intTuple1, 1) == 3); - CuAssertTrue(testCase, stIntTuple_get(intTuple1, 2) == 2); - teardown(); -} - -CuSuite* sonLib_stTuplesTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stIntTuple_construct); - SUITE_ADD_TEST(suite, test_stIntTuple_hashKey); - SUITE_ADD_TEST(suite, test_stIntTuple_cmpFn); - SUITE_ADD_TEST(suite, test_stIntTuple_equalsFn); - SUITE_ADD_TEST(suite, test_stIntTuple_length); - SUITE_ADD_TEST(suite, test_stIntTuple_getPosition); - return suite; -} diff --git a/C/tests/stMatrixTest.c b/C/tests/stMatrixTest.c deleted file mode 100644 index 859e3ac..0000000 --- a/C/tests/stMatrixTest.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2006-2014 by Benedict Paten (benedictpaten@gmail.com) - * - * Released under the MIT license, see LICENSE.txt - */ - -/* - * sonLibMatrixTest.c - * - * Created on: 21-May-2014 - * Author: benedictpaten - */ - -#include "sonLibGlobalsTest.h" - -void test_stMatrixBasics(CuTest *testCase) { - for (int64_t test = 0; test < 100; test++) { - int64_t n = st_randomInt64(0, 10); - int64_t m = st_randomInt64(0, 10); - stMatrix *matrix = stMatrix_construct(n, m); - CuAssertIntEquals(testCase, n, stMatrix_n(matrix)); - CuAssertIntEquals(testCase, m, stMatrix_m(matrix)); - for (int64_t i = 0; i < n; i++) { - for (int64_t j = 0; j < m; j++) { - CuAssertDblEquals(testCase, 0.0, *stMatrix_getCell(matrix, i, j), 0.0); - *stMatrix_getCell(matrix, i, j) = i * j; - CuAssertDblEquals(testCase, i * j, *stMatrix_getCell(matrix, i, j), 0.0); - } - } - stMatrix_destruct(matrix); - } -} - -static stMatrix *getRandomMatrix(int64_t n, int64_t m) { - stMatrix *matrix = stMatrix_construct(n, m); - for (int64_t i = 0; i < n; i++) { - for (int64_t j = 0; j < m; j++) { - *stMatrix_getCell(matrix, i, j) = st_random(); - } - } - return matrix; -} - -void test_stMatrixAdd(CuTest *testCase) { - for (int64_t test = 0; test < 100; test++) { - int64_t n = st_randomInt64(0, 10); - int64_t m = st_randomInt64(0, 10); - stMatrix *matrix1 = getRandomMatrix(n, m); - stMatrix *matrix2 = getRandomMatrix(n, m); - stMatrix *matrix3 = stMatrix_add(matrix1, matrix2); - for (int64_t i = 0; i < n; i++) { - for (int64_t j = 0; j < m; j++) { - CuAssertDblEquals(testCase, *stMatrix_getCell(matrix3, i, j), - *stMatrix_getCell(matrix1, i, j) + *stMatrix_getCell(matrix2, i, j), 0.0); - } - } - stMatrix_destruct(matrix1); - stMatrix_destruct(matrix2); - stMatrix_destruct(matrix3); - } -} - -void test_stMatrixScale(CuTest *testCase) { - for (int64_t test = 0; test < 100; test++) { - int64_t n = st_randomInt64(0, 10); - int64_t m = st_randomInt64(0, 10); - stMatrix *matrix = getRandomMatrix(n, m); - stMatrix *matrix2 = stMatrix_clone(matrix); - stMatrix_scale(matrix, 100, 50); - for (int64_t i = 0; i < n; i++) { - for (int64_t j = 0; j < m; j++) { - CuAssertDblEquals(testCase, (*stMatrix_getCell(matrix2, i, j)) * 100 + 50, *stMatrix_getCell(matrix, i, j), - 0.0); - } - } - stMatrix_destruct(matrix); - stMatrix_destruct(matrix2); - } -} - -void test_stMatrixEqual(CuTest *testCase) { - for (int64_t test = 0; test < 100; test++) { - int64_t n = st_randomInt64(1, 10); - int64_t m = st_randomInt64(1, 10); - stMatrix *matrix1 = getRandomMatrix(n, m); - stMatrix *matrix2 = stMatrix_clone(matrix1); - CuAssertTrue(testCase, stMatrix_equal(matrix1, matrix2, 0.0)); - stMatrix_scale(matrix1, 1.0, 1.0); - CuAssertTrue(testCase, !stMatrix_equal(matrix1, matrix2, 0.0)); - CuAssertTrue(testCase, stMatrix_equal(matrix1, matrix2, 1.0)); - CuAssertTrue(testCase, !stMatrix_equal(matrix1, matrix2, 0.99)); - stMatrix_destruct(matrix1); - stMatrix_destruct(matrix2); - } -} - -void test_stMatrixMultiply(CuTest *testCase) { - stMatrix *m1 = stMatrix_construct(2, 3); - stMatrix *m2 = stMatrix_construct(3, 1); - *stMatrix_getCell(m1, 0, 0) = 1.0; - *stMatrix_getCell(m1, 0, 1) = 2.0; - *stMatrix_getCell(m1, 0, 2) = 3.0; - *stMatrix_getCell(m1, 1, 0) = 4.0; - *stMatrix_getCell(m1, 1, 1) = 5.0; - *stMatrix_getCell(m1, 1, 2) = 6.0; - *stMatrix_getCell(m2, 0, 0) = 7.0; - *stMatrix_getCell(m2, 1, 0) = 8.0; - *stMatrix_getCell(m2, 2, 0) = 9.0; - stMatrix *m3 = stMatrix_multiply(m1, m2); - CuAssertTrue(testCase, stMatrix_n(m3) == 2); - CuAssertTrue(testCase, stMatrix_m(m3) == 1); - CuAssertDblEquals(testCase, *stMatrix_getCell(m3, 0, 0), 50.0, 0.00001); - CuAssertDblEquals(testCase, *stMatrix_getCell(m3, 1, 0), 122.0, 0.00001); - stMatrix_destruct(m1); - stMatrix_destruct(m2); - stMatrix_destruct(m3); -} - -void test_stMatrixMultiplyVector(CuTest *testCase) { - stMatrix *m = stMatrix_construct(2, 2); - double *v = st_calloc(2, sizeof(double)); - *stMatrix_getCell(m, 0, 0) = 2.0; - *stMatrix_getCell(m, 0, 1) = 1.0; - *stMatrix_getCell(m, 1, 0) = 3.0; - *stMatrix_getCell(m, 1, 1) = 5.0; - v[0] = 2.0; - v[1] = 3.0; - double *v2 = stMatrix_multiplySquareMatrixAndColumnVector(m, v); - CuAssertDblEquals(testCase, v2[0], 7.0, 0.00001); - CuAssertDblEquals(testCase, v2[1], 21.0, 0.00001); - stMatrix_destruct(m); - free(v); - free(v2); -} - -void test_stMatrixJukesCantor(CuTest *testCase) { - stMatrix *jukesCantorMatrix = stMatrix_jukesCantor(0.5, 2); - CuAssertTrue(testCase, stMatrix_n(jukesCantorMatrix) == 2); - CuAssertTrue(testCase, stMatrix_m(jukesCantorMatrix) == 2); - CuAssertDblEquals(testCase, *stMatrix_getCell(jukesCantorMatrix, 0, 0), *stMatrix_getCell(jukesCantorMatrix, 1, 1), 0.0); - CuAssertDblEquals(testCase, *stMatrix_getCell(jukesCantorMatrix, 0, 1), *stMatrix_getCell(jukesCantorMatrix, 1, 0), 0.0); - - CuAssertDblEquals(testCase, *stMatrix_getCell(jukesCantorMatrix, 0, 0), 0.5 + 0.5*exp(-1), 0.0); - CuAssertDblEquals(testCase, *stMatrix_getCell(jukesCantorMatrix, 0, 1), 0.5 - 0.5*exp(-1), 0.0); - stMatrix_destruct(jukesCantorMatrix); -} - -CuSuite* sonLib_stMatrixTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_stMatrixBasics); - SUITE_ADD_TEST(suite, test_stMatrixAdd); - SUITE_ADD_TEST(suite, test_stMatrixScale); - SUITE_ADD_TEST(suite, test_stMatrixEqual); - SUITE_ADD_TEST(suite, test_stMatrixMultiply); - SUITE_ADD_TEST(suite, test_stMatrixMultiplyVector); - SUITE_ADD_TEST(suite, test_stMatrixJukesCantor); - - return suite; -} diff --git a/C/tests/stPhylogenyTest.c b/C/tests/stPhylogenyTest.c deleted file mode 100644 index ea4c84b..0000000 --- a/C/tests/stPhylogenyTest.c +++ /dev/null @@ -1,1491 +0,0 @@ -#include -#include -#include "CuTest.h" -#include "sonLib.h" -#include "stPhylogeny.h" - -static stIndexedTreeInfo *getIndex(stTree *node) { - assert(node != NULL); - stPhylogenyInfo *info = stTree_getClientData(node); - assert(info != NULL); - stIndexedTreeInfo *index = info->index; - assert(index != NULL); - return index; -} - -static void testSimpleNeighborJoin(CuTest *testCase) { - int64_t i, j; - // Simple static test, with index 1 very far away from everything, - // 0 and 3 very close, and 2 closer to (0,3) than to 1. - double distances[4][4] = {{0.0, 9.0, 3.0, 0.1}, - {9.0, 0.0, 6.0, 8.9}, - {3.0, 6.0, 0.0, 3.0}, - {0.1, 8.9, 3.0, 0.0}}; - stMatrix * distanceStMatrix = stMatrix_construct(4, 4); - for(i = 0; i < 4; i++) { - for(j = 0; j < 4; j++) { - *stMatrix_getCell(distanceStMatrix, i, j) = distances[i][j]; - } - } - stTree *tree = stPhylogeny_neighborJoin(distanceStMatrix, NULL); - stIndexedTreeInfo *info = getIndex(tree); - - // Check that leavesBelow is correct for the root (every leaf is - // below the root) - for(i = 0; i < 4; i++) { - CuAssertIntEquals(testCase, info->leavesBelow[i], 1); - } - - // We don't want to check the topology, since the root is - // arbitrary (though currently halfway along the longest branch.) - // So instead we check that the distances make sense. 0,3 should be the - // closest together, etc. - CuAssertTrue(testCase, stPhylogeny_distanceBetweenLeaves(tree, 0, 3) < stPhylogeny_distanceBetweenLeaves(tree, 0, 2)); - CuAssertTrue(testCase, stPhylogeny_distanceBetweenLeaves(tree, 0, 3) < stPhylogeny_distanceBetweenLeaves(tree, 0, 1)); - CuAssertTrue(testCase, stPhylogeny_distanceBetweenLeaves(tree, 0, 3) < stPhylogeny_distanceBetweenLeaves(tree, 3, 2)); - CuAssertTrue(testCase, stPhylogeny_distanceBetweenLeaves(tree, 0, 3) < stPhylogeny_distanceBetweenLeaves(tree, 3, 1)); - CuAssertTrue(testCase, stPhylogeny_distanceBetweenLeaves(tree, 0, 2) < stPhylogeny_distanceBetweenLeaves(tree, 0, 1)); - CuAssertTrue(testCase, stPhylogeny_distanceBetweenLeaves(tree, 0, 2) < stPhylogeny_distanceBetweenLeaves(tree, 2, 1)); - - stMatrix_destruct(distanceStMatrix); - stPhylogenyInfo_destructOnTree(tree); - stTree_destruct(tree); -} - -// Score a tree against a few simple "bootstrapped" trees to check -// that identical partitions are counted correctly. -void testSimpleBootstrapPartitionScoring(CuTest *testCase) -{ - stList *bootstraps = stList_construct(); - stTree *tree = stTree_parseNewickString("(((0,1),(2,3)),4);"); - stTree *bootstrap, *result; - stIndexedTreeInfo *index; - stPhylogeny_addStIndexedTreeInfo(tree); - - // An identical tree should give support to all partitions. - bootstrap = stTree_parseNewickString("(4,((1,0),(3,2)));"); - stPhylogeny_addStIndexedTreeInfo(bootstrap); - result = stPhylogeny_scoreFromBootstrap(tree, bootstrap); - index = getIndex(stPhylogeny_getMRCA(result, 4, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - CuAssertTrue(testCase, index->bootstrapSupport == 1.0); - index = getIndex(stPhylogeny_getMRCA(result, 3, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - index = getIndex(stPhylogeny_getMRCA(result, 1, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - index = getIndex(stPhylogeny_getMRCA(result, 3, 2)); - CuAssertTrue(testCase, index->numBootstraps == 1); - stPhylogenyInfo_destructOnTree(result); - stTree_destruct(result); - stList_append(bootstraps, bootstrap); - - // Swapping 0 for 4 - bootstrap = stTree_parseNewickString("(0,((1,4),(3,2)));"); - stPhylogeny_addStIndexedTreeInfo(bootstrap); - result = stPhylogeny_scoreFromBootstrap(tree, bootstrap); - index = getIndex(stPhylogeny_getMRCA(result, 4, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - CuAssertTrue(testCase, index->bootstrapSupport == 1.0); - index = getIndex(stPhylogeny_getMRCA(result, 3, 0)); - CuAssertTrue(testCase, index->numBootstraps == 0); - index = getIndex(stPhylogeny_getMRCA(result, 1, 0)); - CuAssertTrue(testCase, index->numBootstraps == 0); - index = getIndex(stPhylogeny_getMRCA(result, 3, 2)); - CuAssertTrue(testCase, index->numBootstraps == 1); - stPhylogenyInfo_destructOnTree(result); - stTree_destruct(result); - stList_append(bootstraps, bootstrap); - - // Swapping 0 for 3 - bootstrap = stTree_parseNewickString("(4,((1,3),(0,2)));"); - stPhylogeny_addStIndexedTreeInfo(bootstrap); - result = stPhylogeny_scoreFromBootstrap(tree, bootstrap); - index = getIndex(stPhylogeny_getMRCA(result, 4, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - CuAssertTrue(testCase, index->bootstrapSupport == 1.0); - index = getIndex(stPhylogeny_getMRCA(result, 3, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - index = getIndex(stPhylogeny_getMRCA(result, 1, 0)); - CuAssertTrue(testCase, index->numBootstraps == 0); - index = getIndex(stPhylogeny_getMRCA(result, 3, 2)); - CuAssertTrue(testCase, index->numBootstraps == 0); - stPhylogenyInfo_destructOnTree(result); - stTree_destruct(result); - stList_append(bootstraps, bootstrap); - - // Test all 3 together - result = stPhylogeny_scoreFromBootstraps(tree, bootstraps); - index = getIndex(stPhylogeny_getMRCA(result, 4, 0)); - CuAssertTrue(testCase, index->numBootstraps == 3); - index = getIndex(stPhylogeny_getMRCA(result, 3, 0)); - CuAssertTrue(testCase, index->numBootstraps == 2); - index = getIndex(stPhylogeny_getMRCA(result, 1, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - index = getIndex(stPhylogeny_getMRCA(result, 3, 2)); - CuAssertTrue(testCase, index->numBootstraps == 2); - - // Clean up - stPhylogenyInfo_destructOnTree(tree); - stTree_destruct(tree); - stPhylogenyInfo_destructOnTree(result); - stTree_destruct(result); - for(int64_t i = 0; i < stList_length(bootstraps); i++) { - stPhylogenyInfo_destructOnTree(stList_get(bootstraps, i)); - stTree_destruct(stList_get(bootstraps, i)); - } - stList_destruct(bootstraps); -} - -// Set recon info for a tree which already has its stPhylogenyInfo -// set. -static void setReconInfoManually(stTree *tree, const char *nodeLabel, - stTree *species, stReconciliationEvent event) { - stTree *node = stTree_findChild(tree, nodeLabel); - assert(node != NULL); - stPhylogenyInfo *info = stTree_getClientData(node); - assert(info != NULL); - stReconciliationInfo *recon = info->recon; - if (recon == NULL) { - recon = st_malloc(sizeof(stReconciliationInfo)); - info->recon = recon; - } - recon->species = species; - recon->event = event; -} - -// Score a tree against a few simple "bootstrapped" trees to check -// that identical partition with identical reconciliations are counted -// correctly. -void testSimpleBootstrapReconciliationScoring(CuTest *testCase) -{ - stList *bootstraps = stList_construct(); - stTree *tree = stTree_parseNewickString("(((0,1)a,(2,3)b)c,4)d;"); - stTree *bootstrap, *result; - stIndexedTreeInfo *index; - stPhylogeny_addStIndexedTreeInfo(tree); - // Add dummy recon info - - // Dummy species that don't actually point anywhere. A bit nasty, - // but it would be a bug to dereference these anyway. - stTree *s0 = (stTree *) 0; - stTree *s1 = (stTree *) 1; - stTree *s2 = (stTree *) 2; - stTree *s3 = (stTree *) 3; - stTree *s4 = (stTree *) 4; - stTree *s5 = (stTree *) 5; - setReconInfoManually(tree, "0", s0, LEAF); - setReconInfoManually(tree, "1", s1, LEAF); - setReconInfoManually(tree, "2", s0, LEAF); - setReconInfoManually(tree, "3", s1, LEAF); - setReconInfoManually(tree, "4", s4, LEAF); - setReconInfoManually(tree, "a", s2, SPECIATION); - setReconInfoManually(tree, "b", s2, SPECIATION); - setReconInfoManually(tree, "c", s2, DUPLICATION); - setReconInfoManually(tree, "d", s3, SPECIATION); - - // An identical tree with identical reconciliation should give - // support to all partitions. - bootstrap = stTree_parseNewickString("(4,((1,0)a,(3,2)b)c)d;"); - stPhylogeny_addStIndexedTreeInfo(bootstrap); - // Add dummy recon info identical to above - setReconInfoManually(bootstrap, "0", s0, LEAF); - setReconInfoManually(bootstrap, "1", s1, LEAF); - setReconInfoManually(bootstrap, "2", s0, LEAF); - setReconInfoManually(bootstrap, "3", s1, LEAF); - setReconInfoManually(bootstrap, "4", s4, LEAF); - setReconInfoManually(bootstrap, "a", s2, SPECIATION); - setReconInfoManually(bootstrap, "b", s2, SPECIATION); - setReconInfoManually(bootstrap, "c", s2, DUPLICATION); - setReconInfoManually(bootstrap, "d", s3, SPECIATION); - result = stPhylogeny_scoreReconciliationFromBootstrap(tree, bootstrap); - // d - index = getIndex(stPhylogeny_getMRCA(result, 4, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - CuAssertTrue(testCase, index->bootstrapSupport == 1.0); - // c - index = getIndex(stPhylogeny_getMRCA(result, 3, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - // a - index = getIndex(stPhylogeny_getMRCA(result, 1, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - // b - index = getIndex(stPhylogeny_getMRCA(result, 3, 2)); - CuAssertTrue(testCase, index->numBootstraps == 1); - stPhylogenyInfo_destructOnTree(result); - stTree_destruct(result); - stList_append(bootstraps, bootstrap); - - // Swapping 0 for 4 -- the reconciliation support level should - // decrease, even though the reconciliation is identical, because - // it relies on the partitions being the same - bootstrap = stTree_parseNewickString("(0,((1,4)a,(3,2)b)c)d;"); - stPhylogeny_addStIndexedTreeInfo(bootstrap); - // Add dummy recon info identical to above - setReconInfoManually(bootstrap, "0", s0, LEAF); - setReconInfoManually(bootstrap, "1", s1, LEAF); - setReconInfoManually(bootstrap, "2", s0, LEAF); - setReconInfoManually(bootstrap, "3", s1, LEAF); - setReconInfoManually(bootstrap, "4", s4, LEAF); - setReconInfoManually(bootstrap, "a", s2, SPECIATION); - setReconInfoManually(bootstrap, "b", s2, SPECIATION); - setReconInfoManually(bootstrap, "c", s2, DUPLICATION); - setReconInfoManually(bootstrap, "d", s3, SPECIATION); - result = stPhylogeny_scoreReconciliationFromBootstrap(tree, bootstrap); - // d - index = getIndex(stPhylogeny_getMRCA(result, 4, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - CuAssertTrue(testCase, index->bootstrapSupport == 1.0); - // c - index = getIndex(stPhylogeny_getMRCA(result, 3, 0)); - CuAssertTrue(testCase, index->numBootstraps == 0); - // a - index = getIndex(stPhylogeny_getMRCA(result, 1, 0)); - CuAssertTrue(testCase, index->numBootstraps == 0); - // b - index = getIndex(stPhylogeny_getMRCA(result, 3, 2)); - CuAssertTrue(testCase, index->numBootstraps == 1); - // NB: the reconciliation bootstrap support level for leaves is - // not always 1! - // 0 - index = getIndex(stPhylogeny_getLeafByIndex(result, 0)); - CuAssertTrue(testCase, index->numBootstraps == 0); - // 4 - index = getIndex(stPhylogeny_getLeafByIndex(result, 4)); - CuAssertTrue(testCase, index->numBootstraps == 0); - // 2 - index = getIndex(stPhylogeny_getLeafByIndex(result, 2)); - CuAssertTrue(testCase, index->numBootstraps == 1); - - stPhylogenyInfo_destructOnTree(result); - stTree_destruct(result); - stList_append(bootstraps, bootstrap); - - // Different reconciliation but same topology. Test that different - // event (duplication, speciation) labels affect the support value - // as well. - bootstrap = stTree_parseNewickString("(4,((1,0)a,(3,2)b)c)d;"); - stPhylogeny_addStIndexedTreeInfo(bootstrap); - // Add dummy recon info, but this time, the event for a is a - // duplication (impossible in MP reconciliation, but we should - // support it anyway). - setReconInfoManually(bootstrap, "0", s0, LEAF); - setReconInfoManually(bootstrap, "1", s1, LEAF); - setReconInfoManually(bootstrap, "2", s0, LEAF); - setReconInfoManually(bootstrap, "3", s1, LEAF); - setReconInfoManually(bootstrap, "4", s4, LEAF); - setReconInfoManually(bootstrap, "a", s2, DUPLICATION); - setReconInfoManually(bootstrap, "b", s2, SPECIATION); - setReconInfoManually(bootstrap, "c", s2, DUPLICATION); - setReconInfoManually(bootstrap, "d", s5, SPECIATION); - result = stPhylogeny_scoreReconciliationFromBootstrap(tree, bootstrap); - // d - index = getIndex(stPhylogeny_getMRCA(result, 4, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - CuAssertTrue(testCase, index->bootstrapSupport == 1.0); - // c - index = getIndex(stPhylogeny_getMRCA(result, 3, 0)); - CuAssertTrue(testCase, index->numBootstraps == 0); - // a - index = getIndex(stPhylogeny_getMRCA(result, 1, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - // b - index = getIndex(stPhylogeny_getMRCA(result, 3, 2)); - CuAssertTrue(testCase, index->numBootstraps == 1); - // 1 - index = getIndex(stPhylogeny_getLeafByIndex(result, 1)); - CuAssertTrue(testCase, index->numBootstraps == 0); - // 2 - index = getIndex(stPhylogeny_getLeafByIndex(result, 2)); - CuAssertTrue(testCase, index->numBootstraps == 1); - stPhylogenyInfo_destructOnTree(result); - stTree_destruct(result); - stList_append(bootstraps, bootstrap); - - // Test all 3 together - result = stPhylogeny_scoreReconciliationFromBootstraps(tree, bootstraps); - // d - index = getIndex(stPhylogeny_getMRCA(result, 4, 0)); - CuAssertTrue(testCase, index->numBootstraps == 3); - CuAssertTrue(testCase, index->bootstrapSupport == 1.0); - // c - index = getIndex(stPhylogeny_getMRCA(result, 3, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - // a - index = getIndex(stPhylogeny_getMRCA(result, 1, 0)); - CuAssertTrue(testCase, index->numBootstraps == 2); - // b - index = getIndex(stPhylogeny_getMRCA(result, 3, 2)); - CuAssertTrue(testCase, index->numBootstraps == 3); - // 4 - index = getIndex(stPhylogeny_getLeafByIndex(result, 4)); - CuAssertTrue(testCase, index->numBootstraps == 1); - // 3 - index = getIndex(stPhylogeny_getLeafByIndex(result, 3)); - CuAssertTrue(testCase, index->numBootstraps == 3); - // 2 - index = getIndex(stPhylogeny_getLeafByIndex(result, 2)); - CuAssertTrue(testCase, index->numBootstraps == 3); - // 1 - index = getIndex(stPhylogeny_getLeafByIndex(result, 1)); - CuAssertTrue(testCase, index->numBootstraps == 2); - // 0 - index = getIndex(stPhylogeny_getLeafByIndex(result, 0)); - CuAssertTrue(testCase, index->numBootstraps == 1); - stPhylogenyInfo_destructOnTree(result); - stTree_destruct(result); - - // Clean up - stPhylogenyInfo_destructOnTree(tree); - stTree_destruct(tree); - for(int64_t i = 0; i < stList_length(bootstraps); i++) { - stPhylogenyInfo_destructOnTree(stList_get(bootstraps, i)); - stTree_destruct(stList_get(bootstraps, i)); - } - stList_destruct(bootstraps); -} - -static stMatrix *getRandomDistanceMatrix(int64_t size) { - int64_t i, j; - stMatrix *ret = stMatrix_construct(size, size); - for (i = 0; i < size; i++) { - for (j = 0; j <= i; j++) { - double *cell = stMatrix_getCell(ret, i, j); - double val = st_random(); - *cell = val; - // Make sure the other half of the matrix is identical - cell = stMatrix_getCell(ret, size - i - 1, size - j - 1); - *cell = val; - } - } - return ret; -} - -// Test an assert on all nodes of a tree. -static void testOnTree(CuTest *testCase, stTree *tree, - void (*assertFn)(stTree *, CuTest *)) { - int64_t i; - assertFn(tree, testCase); - for (i = 0; i < stTree_getChildNumber(tree); i++) { - testOnTree(testCase, stTree_getChild(tree, i), assertFn); - } -} - -static void checkLeavesBelow(stTree *tree, CuTest *testCase) { - int64_t i; - stIndexedTreeInfo *index = getIndex(tree); - for (i = 0; i < index->totalNumLeaves; i++) { - char *label = stString_print("%" PRIi64, i); - if (index->leavesBelow[i]) { - // leavesBelow says it has leaf i under it -- check - // that it actually does - CuAssertTrue(testCase, stTree_findChild(tree, label) != NULL || - index->matrixIndex == i); - } else { - // leavesBelow says leaf i is not under this node, check - // that it's not - CuAssertTrue(testCase, stTree_findChild(tree, label) == NULL); - } - free(label); - } -} - -// check the stPhylogeny_getLeafByIndex function on a tree. -static void checkGetLeafByIndex(stTree *tree, CuTest *testCase) { - int64_t i; - stIndexedTreeInfo *index = getIndex(tree); - for (i = 0; i < index->totalNumLeaves; i++) { - if (index->leavesBelow[i]) { - stTree *leaf = stPhylogeny_getLeafByIndex(tree, i); - stIndexedTreeInfo *leafIndex = getIndex(leaf); - CuAssertTrue(testCase, leafIndex->matrixIndex == i); - } else { - CuAssertTrue(testCase, stPhylogeny_getLeafByIndex(tree, i) == NULL); - } - } -} - -// Sanity-check the assorted distance functions -static void checkDistanceFunctions(stTree *tree, CuTest *testCase) { - int64_t i, j; - stIndexedTreeInfo *index = getIndex(tree); - for (i = 0; i < index->totalNumLeaves; i++) { - for (j = 0; j < i; j++) { - if (index->leavesBelow[i] && index->leavesBelow[j]) { - // Check that the distance from leaf i to leaf j is the same as - // the distance from j to i - CuAssertDblEquals(testCase, stPhylogeny_distanceBetweenLeaves(tree, i, j), stPhylogeny_distanceBetweenLeaves(tree, j, i), 0.1); - // Check that the distance using distanceBetweenNodes - // is the same as using distanceBetweenLeaves - stTree *iNode = stPhylogeny_getLeafByIndex(tree, i); - stTree *jNode = stPhylogeny_getLeafByIndex(tree, j); - CuAssertDblEquals(testCase, stPhylogeny_distanceBetweenLeaves(tree, i, j), stPhylogeny_distanceBetweenNodes(iNode, jNode), 0.1); - } - } - } - - CuAssertDblEquals(testCase, stPhylogeny_distanceBetweenNodes(tree, tree), 0.0, 0.0); -} - -// Test neighbor-joining on random distance matrices, and test several -// stPhylogeny functions on the resulting trees. -static void testRandomNeighborJoin(CuTest *testCase) { - int64_t testNum; - for (testNum = 0; testNum < 20; testNum++) { - // Run neighbor-joining - int64_t numLeaves = st_randomInt64(3, 300); - stMatrix *matrix = getRandomDistanceMatrix(numLeaves); - bool rootOnOutgroup = st_random() > 0.5; - stList *outgroups = NULL; - - if(rootOnOutgroup) { - // Create outgroup list - outgroups = stList_construct3(0, (void (*)(void *))stIntTuple_destruct); - int64_t numOutgroups = st_randomInt64(1, numLeaves); - for(int64_t i = 0; i < numOutgroups; i++) { - int64_t outgroup = st_randomInt64(0, numLeaves); - stList_append(outgroups, stIntTuple_construct1(outgroup)); - } - } - - stTree *tree = stPhylogeny_neighborJoin(matrix, outgroups); - - if(rootOnOutgroup) { - // Check that the root is placed on one of the outgroup branches. - bool outgroupBranchIsRoot = false; - for(int64_t i = 0; i < stList_length(outgroups); i++) { - int64_t outgroup = stIntTuple_get(stList_get(outgroups, i), 0); - if(stTree_getParent(stTree_getParent(stPhylogeny_getLeafByIndex(tree, outgroup))) == NULL) { - outgroupBranchIsRoot = true; - } - } - CuAssertTrue(testCase, outgroupBranchIsRoot); - stList_destruct(outgroups); - } - - // Check that leavesBelow is set correctly - testOnTree(testCase, tree, checkLeavesBelow); - - // Check that stPhylogeny_getLeafIndex works - testOnTree(testCase, tree, checkGetLeafByIndex); - - // Sanity-check the distance functions. - checkDistanceFunctions(tree, testCase); - - // Clean up - stMatrix_destruct(matrix); - stPhylogenyInfo_destructOnTree(tree); - stTree_destruct(tree); - } -} - -static int64_t numBootstraps; // Totally lazy, but enables - // checkPartitionSupport to see the - // number of bootstraps used - -// Check that the partition-support values on a bootstrap-scored tree -// are all sensible. -static void checkPartitionSupport(stTree *tree, CuTest *testCase) { - stIndexedTreeInfo *index = getIndex(tree); - CuAssertTrue(testCase, index->numBootstraps <= numBootstraps); - CuAssertTrue(testCase, index->numBootstraps >= 0); - CuAssertTrue(testCase, index->bootstrapSupport >= 0.0); - CuAssertTrue(testCase, index->bootstrapSupport <= 1.0); -} - -// Run faux "bootstraps" on random distance matrices of the same size, -// and test several stPhylogeny functions on the resulting trees. -static void testRandomBootstraps(CuTest *testCase) { - stList *bootstraps = stList_construct(); - int64_t matrixSize = st_randomInt64(3, 300); - numBootstraps = st_randomInt64(1, 200); - stMatrix *canonicalMatrix = getRandomDistanceMatrix(matrixSize); - stTree *canonicalTree = stPhylogeny_neighborJoin(canonicalMatrix, NULL); - for(int64_t i = 0; i < numBootstraps; i++) { - // Not a real bootstrap matrix, but the indices are the same - // so the bootstrap code still needs to work. - stMatrix *bootstrapMatrix = getRandomDistanceMatrix(matrixSize); - stTree *bootstrapTree = stPhylogeny_neighborJoin(bootstrapMatrix, NULL); - stList_append(bootstraps, bootstrapTree); - - stMatrix_destruct(bootstrapMatrix); - } - - // Run the code that scores partitions by bootstraps - stTree *bootstrappedTree = stPhylogeny_scoreFromBootstraps(canonicalTree, bootstraps); - - // Check that leavesBelow is set correctly - testOnTree(testCase, bootstrappedTree, checkLeavesBelow); - - // Check that stPhylogeny_getLeafIndex works - testOnTree(testCase, bootstrappedTree, checkGetLeafByIndex); - - // Sanity-check the distance functions. - checkDistanceFunctions(bootstrappedTree, testCase); - - // Root support should always be 1 - stIndexedTreeInfo *rootIndex = getIndex(bootstrappedTree); - CuAssertTrue(testCase, rootIndex->bootstrapSupport == 1.0); - // Check that the parition support numbers are all reasonable - testOnTree(testCase, bootstrappedTree, checkPartitionSupport); - - // Clean up - stMatrix_destruct(canonicalMatrix); - stPhylogenyInfo_destructOnTree(canonicalTree); - stTree_destruct(canonicalTree); - stPhylogenyInfo_destructOnTree(bootstrappedTree); - stTree_destruct(bootstrappedTree); - for(int64_t i = 0; i < stList_length(bootstraps); i++) { - stPhylogenyInfo_destructOnTree(stList_get(bootstraps, i)); - stTree_destruct(stList_get(bootstraps, i)); - } - stList_destruct(bootstraps); -} - -static double getJoinCost(stMatrix *matrix, stHash *speciesToIndex, stTree *tree, const char *label1, const char *label2) { - stTree *node1; - if (strcmp(stTree_getLabel(tree), label1) == 0) { - node1 = tree; - } else { - node1 = stTree_findChild(tree, label1); - } - assert(node1 != NULL); - stTree *node2; - if (strcmp(stTree_getLabel(tree), label2) == 0) { - node2 = tree; - } else { - node2 = stTree_findChild(tree, label2); - } - assert(node2 != NULL); - stIntTuple *index1 = stHash_search(speciesToIndex, node1); - assert(index1 != NULL); - stIntTuple *index2 = stHash_search(speciesToIndex, node2); - assert(index2 != NULL); - int64_t i = stIntTuple_get(index1, 0); - int64_t j = stIntTuple_get(index2, 0); - assert(*stMatrix_getCell(matrix, i, j) == *stMatrix_getCell(matrix, i, j)); - return *stMatrix_getCell(matrix, i, j); -} - -// Make sure the join costs agree with hand calculations on a very -// simple tree. -static void testSimpleJoinCosts(CuTest *testCase) { - stTree *tree = stTree_parseNewickString("((A,B)C,E)D;"); - - // check speciesToIndex is set correctly - stHash *speciesToIndex = stHash_construct2(NULL, (void (*)(void *)) stIntTuple_destruct); - stMatrix *matrix = stPhylogeny_computeJoinCosts(tree, speciesToIndex, 1.0, 0.0); - CuAssertIntEquals(testCase, stTree_getNumNodes(tree), stHash_size(speciesToIndex)); - stSet *seen = stSet_construct3((uint64_t (*)(const void *)) stIntTuple_hashKey, (int (*)(const void *, const void *)) stIntTuple_equalsFn, NULL); - // Make sure there are no duplicate indices and that they are all >= 0. - stHashIterator *hashIt = stHash_getIterator(speciesToIndex); - stTree *curNode; - while ((curNode = stHash_getNext(hashIt)) != NULL) { - stIntTuple *index = stHash_search(speciesToIndex, curNode); - CuAssertTrue(testCase, index != NULL); - CuAssertTrue(testCase, !stSet_search(seen, index)); - CuAssertTrue(testCase, stIntTuple_get(index, 0) >= 0); - } - stHash_destructIterator(hashIt); - stMatrix_destruct(matrix); - stHash_destruct(speciesToIndex); - - // check dups - speciesToIndex = stHash_construct2(NULL, (void (*)(void *)) stIntTuple_destruct); - matrix = stPhylogeny_computeJoinCosts(tree, speciesToIndex, 1.0, 0.0); - CuAssertDblEquals(testCase, 1.0, getJoinCost(matrix, speciesToIndex, tree, "A", "A"), 0.01); - CuAssertDblEquals(testCase, 0.0, getJoinCost(matrix, speciesToIndex, tree, "A", "B"), 0.01); - CuAssertDblEquals(testCase, 0.0, getJoinCost(matrix, speciesToIndex, tree, "B", "A"), 0.01); - CuAssertDblEquals(testCase, 0.0, getJoinCost(matrix, speciesToIndex, tree, "A", "E"), 0.01); - CuAssertDblEquals(testCase, 1.0, getJoinCost(matrix, speciesToIndex, tree, "A", "D"), 0.01); - CuAssertDblEquals(testCase, 1.0, getJoinCost(matrix, speciesToIndex, tree, "A", "C"), 0.01); - CuAssertDblEquals(testCase, 1.0, getJoinCost(matrix, speciesToIndex, tree, "C", "A"), 0.01); - CuAssertDblEquals(testCase, 1.0, getJoinCost(matrix, speciesToIndex, tree, "D", "D"), 0.01); - stMatrix_destruct(matrix); - stHash_destruct(speciesToIndex); - - // check losses - speciesToIndex = stHash_construct2(NULL, (void (*)(void *)) stIntTuple_destruct); - matrix = stPhylogeny_computeJoinCosts(tree, speciesToIndex, 0.0, 1.0); - CuAssertDblEquals(testCase, 0.0, getJoinCost(matrix, speciesToIndex, tree, "A", "A"), 0.01); - CuAssertDblEquals(testCase, 0.0, getJoinCost(matrix, speciesToIndex, tree, "A", "B"), 0.01); - CuAssertDblEquals(testCase, 0.0, getJoinCost(matrix, speciesToIndex, tree, "B", "A"), 0.01); - CuAssertDblEquals(testCase, 1.0, getJoinCost(matrix, speciesToIndex, tree, "A", "E"), 0.01); - CuAssertDblEquals(testCase, 2.0, getJoinCost(matrix, speciesToIndex, tree, "A", "D"), 0.01); - CuAssertDblEquals(testCase, 1.0, getJoinCost(matrix, speciesToIndex, tree, "A", "C"), 0.01); - CuAssertDblEquals(testCase, 1.0, getJoinCost(matrix, speciesToIndex, tree, "C", "A"), 0.01); - CuAssertDblEquals(testCase, 0.0, getJoinCost(matrix, speciesToIndex, tree, "D", "D"), 0.01); - - stMatrix_destruct(matrix); - stHash_destruct(speciesToIndex); - stSet_destruct(seen); - stTree_destruct(tree); -} - -// get a random binary tree. numLeaves will get set to the eventual -// number of leaves. -static stTree *getRandomBinaryTree(int64_t maxDepth, int64_t *numLeaves) { - stTree *ret = stTree_construct(); - int64_t numChildren = st_random() > 0.5 ? 2 : 0; - if (maxDepth != 0) { - for (int64_t i = 0; i < numChildren; i++) { - stTree_setParent(getRandomBinaryTree(maxDepth - 1, numLeaves), ret); - } - } - if (stTree_getChildNumber(ret) == 0) { - char *name = stString_print("%" PRIi64, (*numLeaves)++); - stTree_setLabel(ret, name); - free(name); - } - return ret; -} - -// Test that the join costs are equal to what the reconciliation cost -// functions would suggest. -static void testJoinCosts_random(CuTest *testCase) { - for (int64_t testNum = 0; testNum < 100; testNum++) { - int64_t numSpeciesLeaves = 0; - stTree *speciesTree = getRandomBinaryTree(st_randomInt64(2, 4), - &numSpeciesLeaves); - int64_t numSpecies = stTree_getNumNodes(speciesTree); - stHash *speciesToIndex = stHash_construct2(NULL, (void (*)(void *)) stIntTuple_destruct); - double dupCost = st_random(); - double lossCost = st_random(); - stMatrix *joinCosts = stPhylogeny_computeJoinCosts(speciesTree, - speciesToIndex, - dupCost, lossCost); - stHash *indexToSpecies = stHash_invert(speciesToIndex, (uint64_t (*)(const void *)) stIntTuple_hashKey, (int (*)(const void *, const void *)) stIntTuple_equalsFn, NULL, NULL); - for (int64_t i = 0; i < numSpecies; i++) { - for (int64_t j = 0; j < numSpecies; j++) { - // Check that the tree joining these two nodes really - // would get the same join cost according to the - // reconciliation cost functions. - stTree *geneTree = stTree_parseNewickString("(I,J)MRCA;"); - stTree *iNode = stTree_findChild(geneTree, "I"); - assert(iNode != NULL); - stTree *jNode = stTree_findChild(geneTree, "J"); - assert(jNode != NULL); - // Construct the initial reconciliation for the leaves - // of the gene tree. - stHash *leafToSpecies = stHash_construct(); - stIntTuple *query = stIntTuple_construct1(i); - stTree *iSpecies = stHash_search(indexToSpecies, query); - assert(iSpecies != NULL); - stIntTuple_destruct(query); - stHash_insert(leafToSpecies, iNode, iSpecies); - query = stIntTuple_construct1(j); - stTree *jSpecies = stHash_search(indexToSpecies, query); - assert(jSpecies != NULL); - stIntTuple_destruct(query); - stHash_insert(leafToSpecies, jNode, jSpecies); - // Reconcile the tree and calculate the join cost we expect. - stPhylogeny_reconcileAtMostBinary(geneTree, leafToSpecies, false); - int64_t dups = 0, losses = 0; - stPhylogeny_reconciliationCostAtMostBinary(geneTree, &dups, - &losses); - double expectedCost = dupCost * dups + lossCost * losses; - double actualCost = *stMatrix_getCell(joinCosts, i, j); - CuAssertDblEquals(testCase, *stMatrix_getCell(joinCosts, i, j), - *stMatrix_getCell(joinCosts, i, j), 0.01); - CuAssertDblEquals(testCase, expectedCost, actualCost, 0.01); - stHash_destruct(leafToSpecies); - stPhylogenyInfo_destructOnTree(geneTree); - stTree_destruct(geneTree); - } - } - stHash_destruct(indexToSpecies); - stHash_destruct(speciesToIndex); - stTree_destruct(speciesTree); - stMatrix_destruct(joinCosts); - } -} - -static stMatrix *getRandomSimilarityMatrix(int64_t size, int64_t maxNumSimilarities, int64_t maxNumDifferences) { - stMatrix *ret = stMatrix_construct(size, size); - for (int64_t i = 0; i < size; i++) { - for (int64_t j = i + 1; j < size; j++) { - double similarities = st_random() * maxNumSimilarities; - double differences = st_random() * maxNumDifferences; - *stMatrix_getCell(ret, i, j) = similarities; - *stMatrix_getCell(ret, j, i) = differences; - } - } - return ret; -} - -static stMatrix *getDistanceMatrixFromSimilarityMatrix(stMatrix *similarityMatrix) { - assert(stMatrix_n(similarityMatrix) == stMatrix_m(similarityMatrix)); - stMatrix *ret = stMatrix_construct(stMatrix_n(similarityMatrix), stMatrix_m(similarityMatrix)); - for (int64_t i = 0; i < stMatrix_n(ret); i++) { - for (int64_t j = i + 1; j < stMatrix_m(ret); j++) { - double similarities = *stMatrix_getCell(similarityMatrix, i, j); - double differences = *stMatrix_getCell(similarityMatrix, j, i); - double count = similarities + differences; - *stMatrix_getCell(ret, i, j) = (count != 0.0) ? differences / count : INT64_MAX; - *stMatrix_getCell(ret, j, i) = (count != 0.0) ? differences / count : INT64_MAX; - } - } - return ret; -} - -static bool isTopologyEqual(stTree *tree1, stTree *tree2) { - if (stTree_getChildNumber(tree1) != stTree_getChildNumber(tree2)) { - return false; - } - - for (int64_t i = 0; i < stTree_getChildNumber(tree1); i++) { - stTree *child1 = stTree_getChild(tree1, i); - // Find matching child in tree2. - stIndexedTreeInfo *index1 = getIndex(child1); - stTree *matchingChild = NULL; - for (int64_t j = 0; j < stTree_getChildNumber(tree2); j++) { - stTree *child2 = stTree_getChild(tree2, j); - stIndexedTreeInfo *index2 = getIndex(child2); - if (index1->totalNumLeaves != index2->totalNumLeaves) { - return false; - } - if (!memcmp(index1->leavesBelow, index2->leavesBelow, index1->totalNumLeaves)) { - // Found correct child - matchingChild = child2; - break; - } - } - if (matchingChild == NULL) { - return false; - } - if (!isTopologyEqual(child1, matchingChild)) { - return false; - } - } - return true; -} - -static void testGuidedNeighborJoiningReducesToNeighborJoining(CuTest *testCase) { - for (int64_t testNum = 0; testNum < 100; testNum++) { - // Get a random species tree. - int64_t numSpecies = 0; - stTree *speciesTree = getRandomBinaryTree(st_randomInt64(2, 7), &numSpecies); - if (numSpecies < 3) { - stTree_destruct(speciesTree); - continue; - } - - // Join cost stuff - stHash *speciesToIndex = stHash_construct2(NULL, (void (*)(void *)) stIntTuple_destruct); - stMatrix *joinCosts = stPhylogeny_computeJoinCosts(speciesTree, speciesToIndex, 0.0, 0.0); - - stMatrix *similarityMatrix = getRandomSimilarityMatrix(numSpecies, 50, 50); - stMatrix *distanceMatrix = getDistanceMatrixFromSimilarityMatrix(similarityMatrix); - stTree *neighborJoiningTree = stPhylogeny_neighborJoin(distanceMatrix, NULL); - - stHash *matrixIndexToJoinCostIndex = stHash_construct3((uint64_t (*)(const void *)) stIntTuple_hashKey, (int (*)(const void *, const void *)) stIntTuple_equalsFn, (void (*)(void *)) stIntTuple_destruct, (void (*)(void *)) stIntTuple_destruct); - // assign the matrix indices to be equal to the species indices. - for (int64_t i = 0; i < numSpecies; i++) { - stIntTuple *iTuple = stIntTuple_construct1(i); - char *speciesName = stString_print("%" PRIi64, i); - stIntTuple *joinCostIndex = stHash_search(speciesToIndex, stTree_findChild(speciesTree, speciesName)); - stHash_insert(matrixIndexToJoinCostIndex, iTuple, stIntTuple_construct1(stIntTuple_get(joinCostIndex, 0))); - free(speciesName); - } - // Get the MRCA matrix - int64_t **speciesMRCAMatrix = stPhylogeny_getMRCAMatrix(speciesTree, speciesToIndex); - - stTree *guidedNeighborJoiningTree = stPhylogeny_guidedNeighborJoining(distanceMatrix, similarityMatrix, joinCosts, matrixIndexToJoinCostIndex, speciesToIndex, speciesMRCAMatrix, speciesTree); - - for(int i = 0; i < stTree_getNumNodes(speciesTree); i++) { - free(speciesMRCAMatrix[i]); - } - free(speciesMRCAMatrix); - - // Root both the trees the same way (above node 0) - stPhylogenyInfo_destructOnTree(neighborJoiningTree); - stPhylogenyInfo_destructOnTree(guidedNeighborJoiningTree); - stTree *tmp = stTree_findChild(neighborJoiningTree, "0"); - stTree *rootedNeighborJoiningTree = stTree_reRoot(tmp, stTree_getBranchLength(tmp)/2); - tmp = stTree_findChild(guidedNeighborJoiningTree, "0"); - stTree *rootedGuidedNeighborJoiningTree = stTree_reRoot(tmp, stTree_getBranchLength(tmp)/2); - stPhylogeny_addStIndexedTreeInfo(rootedNeighborJoiningTree); - stPhylogeny_addStIndexedTreeInfo(rootedGuidedNeighborJoiningTree); - - // Check that the topologies are the same in neighbor-joining - // vs guided neighbor-joining (when they are rooted the same way) - CuAssertTrue(testCase, isTopologyEqual(rootedNeighborJoiningTree, rootedGuidedNeighborJoiningTree)); - - // Clean up. - stPhylogenyInfo_destructOnTree(rootedGuidedNeighborJoiningTree); - stTree_destruct(rootedGuidedNeighborJoiningTree); - stPhylogenyInfo_destructOnTree(rootedNeighborJoiningTree); - stTree_destruct(rootedNeighborJoiningTree); - stTree_destruct(guidedNeighborJoiningTree); - stTree_destruct(neighborJoiningTree); - stTree_destruct(speciesTree); - stMatrix_destruct(similarityMatrix); - stMatrix_destruct(distanceMatrix); - stMatrix_destruct(joinCosts); - stHash_destruct(matrixIndexToJoinCostIndex); - stHash_destruct(speciesToIndex); - } -} - -// Check that when join costs are ratcheted up to insane levels, the -// tree produced has minimal reconciliation cost. -static void testGuidedNeighborJoiningLowersReconCost(CuTest *testCase) -{ - for (int64_t testNum = 0; testNum < 100; testNum++) { - // Get a random species tree. - int64_t numSpecies = 0; - stTree *speciesTree = getRandomBinaryTree(st_randomInt64(2, 7), &numSpecies); - if (numSpecies < 3) { - stTree_destruct(speciesTree); - continue; - } - - // Join cost stuff - stHash *speciesToIndex = stHash_construct2(NULL, (void (*)(void *)) stIntTuple_destruct); - stMatrix *joinCosts = stPhylogeny_computeJoinCosts(speciesTree, speciesToIndex, 100000.0, 100000.0); - - // Create a set of genes of size n*(num species), where each leaf - // species is mapped to n genes. We'd like the guided neighbor - // joining process to create a tree that can be reconciled so that - // there are only n dups. - int64_t numGenesPerSpecies = st_randomInt64(2, 5); - stMatrix *similarityMatrix = getRandomSimilarityMatrix(numSpecies*numGenesPerSpecies, 50, 50); - // assign the matrix indices i, 2i, 3i, ... to map to species index i. - stHash *matrixIndexToJoinCostIndex = stHash_construct3((uint64_t (*)(const void *)) stIntTuple_hashKey, (int (*)(const void *, const void *)) stIntTuple_equalsFn, (void (*)(void *)) stIntTuple_destruct, (void (*)(void *)) stIntTuple_destruct); - for (int64_t i = 0; i < numSpecies; i++) { - char *speciesName = stString_print("%" PRIi64, i); - stIntTuple *joinCostIndex = stHash_search(speciesToIndex, stTree_findChild(speciesTree, speciesName)); - for (int64_t j = i; j < numGenesPerSpecies * numSpecies; j += numSpecies) { - stIntTuple *matrixIndex = stIntTuple_construct1(j); - stHash_insert(matrixIndexToJoinCostIndex, matrixIndex, stIntTuple_construct1(stIntTuple_get(joinCostIndex, 0))); - } - free(speciesName); - } - - // get MRCA matrix - int64_t **speciesMRCAMatrix = stPhylogeny_getMRCAMatrix(speciesTree, speciesToIndex); - - // get distance matrix - stMatrix *distanceMatrix = getDistanceMatrixFromSimilarityMatrix(similarityMatrix); - - stTree *guidedNeighborJoiningTree = stPhylogeny_guidedNeighborJoining(distanceMatrix, similarityMatrix, joinCosts, matrixIndexToJoinCostIndex, speciesToIndex, speciesMRCAMatrix, speciesTree); - - stMatrix_destruct(distanceMatrix); - for(int i = 0; i < stTree_getNumNodes(speciesTree); i++) { - free(speciesMRCAMatrix[i]); - } - free(speciesMRCAMatrix); - - // Build the gene->species mapping for the reconciliation algorithm. - stHash *leafToSpecies = stHash_construct(); - for (int64_t i = 0; i < numSpecies; i++) { - char *speciesName = stString_print("%" PRIi64, i); - stTree *species = stTree_findChild(speciesTree, speciesName); - for (int64_t j = i; j < numGenesPerSpecies * numSpecies; j += numSpecies) { - char *geneName = stString_print("%" PRIi64, j); - stTree *gene = stTree_findChild(guidedNeighborJoiningTree, geneName); - stHash_insert(leafToSpecies, gene, species); - free(geneName); - } - free(speciesName); - } - - // Now check that the gene tree we get out of the algorithm has - // minimal reconcilation cost due to the very high join costs (in - // this case, the number of dups should be equal to the number of - // "extra" genes per species). - int64_t dups = 0, losses = 0; - stPhylogeny_reconcileAtMostBinary(guidedNeighborJoiningTree, - leafToSpecies, false); - stPhylogeny_reconciliationCostAtMostBinary(guidedNeighborJoiningTree, - &dups, &losses); - CuAssertTrue(testCase, losses == 0); - CuAssertTrue(testCase, dups == numGenesPerSpecies - 1); - - // Clean up. - stTree_destruct(speciesTree); - stHash_destruct(matrixIndexToJoinCostIndex); - stHash_destruct(speciesToIndex); - stHash_destruct(leafToSpecies); - stPhylogenyInfo_destructOnTree(guidedNeighborJoiningTree); - stTree_destruct(guidedNeighborJoiningTree); - stMatrix_destruct(similarityMatrix); - stMatrix_destruct(joinCosts); - } -} - -// Globals for checkMinimalReconScore -stTree *globalSpeciesTree; -stHash *globalLeafToSpecies; -int64_t bestDups; -int64_t bestLosses; - -// Check that the tree rooted above this node doesn't have a lower cost -// than the "best" cost. -static void checkMinimalReconScore(stTree *tree, CuTest *testCase) { - stTree *newRootedTree = stTree_reRoot(tree, 0.0); - stPhylogeny_addStIndexedTreeInfo(newRootedTree); - // This is pretty stupid, but we have to map from the - // leafToSpecies on the old gene tree to this rerooted - // one. TODO: Probably the leafToSpecies concept needs to be rethought. - // Probably should use matrix index -> species node instead. - stHash *myLeafToSpecies = stHash_construct(); - stHashIterator *hashIt = stHash_getIterator(globalLeafToSpecies); - stTree *curGene; // Current gene in the old leafToSpecies. - while((curGene = stHash_getNext(hashIt)) != NULL) { - stIndexedTreeInfo *index = getIndex(curGene); - stTree *species = stHash_search(globalLeafToSpecies, curGene); - stTree *newGene = stPhylogeny_getLeafByIndex(newRootedTree, index->matrixIndex); - stHash_insert(myLeafToSpecies, newGene, species); - } - - // Check the cost. - stPhylogeny_reconcileAtMostBinary(newRootedTree, myLeafToSpecies, false); - int64_t dups = 0, losses = 0; - stPhylogeny_reconciliationCostAtMostBinary(newRootedTree, &dups, &losses); - CuAssertTrue(testCase, dups >= bestDups); - if (dups == bestDups) { - CuAssertTrue(testCase, losses >= bestLosses); - } - CuAssertTrue(testCase, dups + losses >= 0); - stHash_destruct(myLeafToSpecies); - stPhylogenyInfo_destructOnTree(newRootedTree); - stTree_destruct(newRootedTree); - stHash_destructIterator(hashIt); -} - -static void testStPhylogeny_rootByReconciliationAtMostBinary_simpleTests(CuTest *testCase) { - // First off -- sanity check that reconciling a gene tree equal to - // a species tree is a no-op. - int64_t numLeaves = st_randomInt64(3, 300); - stMatrix *matrix = getRandomDistanceMatrix(numLeaves); - stTree *speciesTree = stPhylogeny_neighborJoin(matrix, NULL); - stTree *geneTree = stTree_clone(speciesTree); - stHash *leafToSpecies = stHash_construct(); - for(int64_t i = 0; i < numLeaves; i++) { - stTree *gene = stPhylogeny_getLeafByIndex(geneTree, i); - stTree *species = stPhylogeny_getLeafByIndex(speciesTree, i); - stHash_insert(leafToSpecies, gene, species); - } - stTree *rooted = stPhylogeny_rootByReconciliationAtMostBinary(geneTree, - leafToSpecies); - CuAssertTrue(testCase, stTree_equals(rooted, geneTree)); - // Check that the cost is 0. - int64_t dups = 0, losses = 0; - stPhylogeny_reconcileAtMostBinary(geneTree, leafToSpecies, false); - stPhylogeny_reconciliationCostAtMostBinary(geneTree, &dups, &losses); - CuAssertTrue(testCase, dups == 0); - CuAssertTrue(testCase, losses == 0); - - stPhylogenyInfo_destructOnTree(speciesTree); - stMatrix_destruct(matrix); - stTree_destruct(speciesTree); - stTree_destruct(geneTree); - stTree_destruct(rooted); - stHash_destruct(leafToSpecies); - - // Test an annoying example that didn't get rooted right. - stTree *foo = stTree_parseNewickString("(((0:1,1:1):1,2:1):1,3:1);"); - speciesTree = stTree_parseNewickString("((mouse,rat)mr,human)mrh;"); - leafToSpecies = stHash_construct(); - stHash_insert(leafToSpecies, stTree_findChild(foo, "0"), stTree_findChild(speciesTree, "rat")); - stHash_insert(leafToSpecies, stTree_findChild(foo, "1"), stTree_findChild(speciesTree, "mouse")); - stHash_insert(leafToSpecies, stTree_findChild(foo, "2"), stTree_findChild(speciesTree, "human")); - stHash_insert(leafToSpecies, stTree_findChild(foo, "3"), stTree_findChild(speciesTree, "human")); - rooted = stPhylogeny_rootByReconciliationAtMostBinary(foo, leafToSpecies); - char *s = stTree_getNewickTreeString(rooted); - CuAssertStrEquals(testCase, "((0:1,1:1):0.5,(2:1,3:2):0.5);", s); - free(s); - stPhylogenyInfo_destructOnTree(foo); - stTree_destruct(foo); - stTree_destruct(speciesTree); - stTree_destruct(rooted); - stHash_destruct(leafToSpecies); - -} - -// Make sure that the tree given by rootByReconciliationAtMostBinary -// is a tree with the lowest possible dup cost, with loss cost as -// tiebreaker. -static void testStPhylogeny_rootByReconciliationAtMostBinary_random(CuTest *testCase) { - for(int64_t testNum = 0; testNum < 1; testNum++) { - int64_t numSpecies = st_randomInt64(3, 50); - stMatrix *matrix = getRandomDistanceMatrix(numSpecies); - globalSpeciesTree = stPhylogeny_neighborJoin(matrix, NULL); - int64_t numGenes = st_randomInt64(3, 100); - stMatrix_destruct(matrix); - matrix = getRandomDistanceMatrix(numGenes); - stTree *geneTree = stPhylogeny_neighborJoin(matrix, NULL); - stMatrix_destruct(matrix); - - // Assign genes to random species. - globalLeafToSpecies = stHash_construct(); - for(int64_t i = 0; i < numGenes; i++) { - stTree *gene = stPhylogeny_getLeafByIndex(geneTree, i); - stTree *species = stPhylogeny_getLeafByIndex(globalSpeciesTree, st_randomInt64(0, numSpecies)); - stHash_insert(globalLeafToSpecies, gene, species); - } - - // Find the best rooting using either the naive or optimized version. - stTree *rooted; - if (st_random() > 0.5) { - rooted = stPhylogeny_rootByReconciliationAtMostBinary(geneTree, globalLeafToSpecies); - } else { - rooted = stPhylogeny_rootByReconciliationNaive(geneTree, globalLeafToSpecies); - } - stPhylogeny_addStIndexedTreeInfo(rooted); - // This is pretty stupid, but we have to map from the - // leafToSpecies on the old gene tree to this rerooted - // one. - // Probably should use matrix index -> species node instead. - stHash *myLeafToSpecies = stHash_construct(); - stHashIterator *hashIt = stHash_getIterator(globalLeafToSpecies); - stTree *curGene; // Current gene in the old leafToSpecies. - while((curGene = stHash_getNext(hashIt)) != NULL) { - stIndexedTreeInfo *index = getIndex(curGene); - stTree *species = stHash_search(globalLeafToSpecies, curGene); - stTree *newGene = stPhylogeny_getLeafByIndex(rooted, index->matrixIndex); - stHash_insert(myLeafToSpecies, newGene, species); - } - stHash_destructIterator(hashIt); - stPhylogeny_reconcileAtMostBinary(rooted, myLeafToSpecies, false); - int64_t dups = 0, losses = 0; - stPhylogeny_reconciliationCostAtMostBinary(rooted, &dups, &losses); - bestDups = dups; - bestLosses = losses; - CuAssertTrue(testCase, bestDups >= 0); - CuAssertTrue(testCase, losses >= 0); - - // Now check all possible roots and confirm that there isn't a - // better one. - testOnTree(testCase, geneTree, checkMinimalReconScore); - stPhylogenyInfo_destructOnTree(rooted); - stTree_destruct(rooted); - stPhylogenyInfo_destructOnTree(geneTree); - stTree_destruct(geneTree); - stPhylogenyInfo_destructOnTree(globalSpeciesTree); - stTree_destruct(globalSpeciesTree); - stHash_destruct(myLeafToSpecies); - } -} - -/* - * Test that the atMostBinary reconciliation functions work correctly - * with trees that have nodes that have in-degree 1, out-degree 1. - */ -static void testStPhylogeny_reconcileAtMostBinary_degree2Nodes(CuTest *testCase) { - stTree *speciesTree = stTree_parseNewickString("(((A,B)F)G,((C,D)H,(E)I)J)K;"); - // First test a gene tree that similar to the species tree, but A - // and B are children of G now, and E is a child of J. It should - // have no reconciliation cost and the best root should be the - // current one. - stTree *geneTree = stTree_parseNewickString("((A,B)G,((C,D)H,E)J)K;"); - // Create the leaf->species hash (mapping A->A, B->B, etc.) - stHash *leafToSpecies = stHash_construct(); - for (char label = 'A'; label <= 'E'; label++) { - char labelStr[2]; - labelStr[0] = label; - labelStr[1] = '\0'; - stTree *leaf = stTree_findChild(geneTree, labelStr); - stTree *species = stTree_findChild(speciesTree, labelStr); - stHash_insert(leafToSpecies, leaf, species); - } - stPhylogeny_reconcileAtMostBinary(geneTree, leafToSpecies, true); - int64_t dups = 0, losses = 0; - stPhylogeny_reconciliationCostAtMostBinary(geneTree, &dups, &losses); - CuAssertIntEquals(testCase, 0, dups); - CuAssertIntEquals(testCase, 0, losses); - - stHash_destruct(leafToSpecies); - stPhylogenyInfo_destructOnTree(geneTree); - stTree_destruct(geneTree); - - // Check that if E is gone we still get a (single) loss. - geneTree = stTree_parseNewickString("((A,B)F,(C,D)H)K;"); - // Create the leaf->species hash (mapping A->A, B->B, etc.) - leafToSpecies = stHash_construct(); - for (char label = 'A'; label <= 'D'; label++) { - char labelStr[2]; - labelStr[0] = label; - labelStr[1] = '\0'; - stTree *leaf = stTree_findChild(geneTree, labelStr); - stTree *species = stTree_findChild(speciesTree, labelStr); - stHash_insert(leafToSpecies, leaf, species); - } - stPhylogeny_reconcileAtMostBinary(geneTree, leafToSpecies, true); - dups = 0; - losses = 0; - stPhylogeny_reconciliationCostAtMostBinary(geneTree, &dups, &losses); - CuAssertIntEquals(testCase, 0, dups); - CuAssertIntEquals(testCase, 1, losses); - - stHash_destruct(leafToSpecies); - stPhylogenyInfo_destructOnTree(geneTree); - stTree_destruct(geneTree); - stTree_destruct(speciesTree); -} - -// Build a leaf to species hash using the labels of the leaves, -// assuming that the label format is 'species-gene'. -static stHash *buildLeafToSpeciesUsingDashSeparator(stTree *geneTree, stTree *speciesTree) { - stHash *leafToSpecies = stHash_construct(); - stList *dfStack = stList_construct(); - stList_append(dfStack, geneTree); - while (stList_length(dfStack) != 0) { - stTree *node = stList_pop(dfStack); - for (int64_t i = 0; i < stTree_getChildNumber(node); i++) { - stList_append(dfStack, stTree_getChild(node, i)); - } - if (stTree_getChildNumber(node) == 0) { - // Assign the leaves to their species by using the first - // '-'-separated token. - stList *tokens = stString_splitByString(stTree_getLabel(node), "-"); - char *speciesName = stList_get(tokens, 0); - stTree *species = stTree_findChild(speciesTree, speciesName); - assert(species != NULL); - stHash_insert(leafToSpecies, node, species); - stList_destruct(tokens); - } - } - stList_destruct(dfStack); - return leafToSpecies; -} - -static void testStPhylogeny_reconcileNonBinary(CuTest *testCase) { - // TEST 1: "exercise5" tree provided with Notung. - stTree *speciesTree = stTree_parseNewickString("((tasmanian_devil,opossum,bandicoot,kangaroo)Metatheria,((mouse,human)Euarchontoglires,cow)Boreoeutheria)Theria;"); - stTree *geneTree = stTree_parseNewickString("((((opossum-gene1,tasmanian_devil-gene1),kangaroo-gene1),((mouse-gene,human-gene),cow-gene)),((opossum-gene2,kangaroo-gene2),(bandicoot-gene3,kangaroo-gene3)));"); - // Assign the initial reconciliation - stHash *leafToSpecies = buildLeafToSpeciesUsingDashSeparator(geneTree, speciesTree); - - // Do the reconciliation and check that the mapping matches. - stPhylogeny_reconcileNonBinary(geneTree, leafToSpecies, true); - char *testNewick = stTree_getNewickTreeString(geneTree); - CuAssertStrEquals(testCase, "((((opossum-gene1,tasmanian_devil-gene1)Metatheria,kangaroo-gene1)Metatheria,((mouse-gene,human-gene)Euarchontoglires,cow-gene)Boreoeutheria)Theria,((opossum-gene2,kangaroo-gene2)Metatheria,(bandicoot-gene3,kangaroo-gene3)Metatheria)Metatheria)Theria;", testNewick); - free(testNewick); - - // Check that the ILSed node in the tree is not marked as a - // duplication (since it's only a conditional duplication). - stTree *node = stTree_getMRCA(stTree_findChild(geneTree, "opossum-gene1"), stTree_findChild(geneTree, "kangaroo-gene1")); - stPhylogenyInfo *info = stTree_getClientData(node); - CuAssertTrue(testCase, info->recon->event == SPECIATION); - - // Check that the duplication along lineage "2" is correctly identified. - node = stTree_getMRCA(stTree_findChild(geneTree, "opossum-gene2"), stTree_findChild(geneTree, "kangaroo-gene3")); - info = stTree_getClientData(node); - CuAssertTrue(testCase, info->recon->event == DUPLICATION); - - // Check that the duplication in the root is correctly identified. - node = geneTree; - info = stTree_getClientData(node); - CuAssertTrue(testCase, info->recon->event == DUPLICATION); - - // Clean up. - stPhylogenyInfo_destructOnTree(geneTree); - stTree_destruct(geneTree); - stTree_destruct(speciesTree); - stHash_destruct(leafToSpecies); - - // TEST 2: Fig 3 in Notung paper. - speciesTree = stTree_parseNewickString("(A,B,(C,D)Beta)Alpha;"); - geneTree = stTree_parseNewickString("(A-g1,((B-g3,C-g3),D-g2));"); - - leafToSpecies = buildLeafToSpeciesUsingDashSeparator(geneTree, speciesTree); - - // Reconcile and check the reconciliation gene->species - // assignments are correct - stPhylogeny_reconcileNonBinary(geneTree, leafToSpecies, true); - testNewick = stTree_getNewickTreeString(geneTree); - CuAssertStrEquals(testCase, "(A-g1,((B-g3,C-g3)Alpha,D-g2)Alpha)Alpha;", testNewick); - free(testNewick); - - // Even though there are 3 nodes reconciled to Alpha, there should - // be only one duplication node, and it should be where the "g3" - // and "g2" lineages coalesce. - - node = stTree_getMRCA(stTree_findChild(geneTree, "B-g3"), stTree_findChild(geneTree, "C-g3")); - info = stTree_getClientData(node); - CuAssertTrue(testCase, info->recon->event == SPECIATION); - - node = stTree_getMRCA(stTree_findChild(geneTree, "B-g3"), stTree_findChild(geneTree, "D-g2")); - info = stTree_getClientData(node); - CuAssertTrue(testCase, info->recon->event == DUPLICATION); - - node = stTree_getMRCA(stTree_findChild(geneTree, "B-g3"), stTree_findChild(geneTree, "A-g1")); - info = stTree_getClientData(node); - CuAssertTrue(testCase, info->recon->event == SPECIATION); - - // Clean up. - stPhylogenyInfo_destructOnTree(geneTree); - stTree_destruct(geneTree); - stTree_destruct(speciesTree); - stHash_destruct(leafToSpecies); -} - -static void testStPhylogeny_nni(CuTest *testCase) { - stTree *geneTree = stTree_parseNewickString("(NZOHlLtJ.chr9_87081620_87115187|0|16656-16694.30:0.000120563,((C57B6J.9_87174839_87208406|16656-16694.30:0.0001,C57B6NJ.chr9_90403979_90439438|16656-16694.27:0.0001)27:0.00132877,(C57B6NJ.chr9_90403979_90439438|18548-18586.29:0.00113208,(C57B6NJ.chr1_3987551_4018377|20930-20968.30:0.0001,C57B6NJ.chr1_3987551_4018377|15210-15248.30:0.0001)branch:0.0554717)27:0.00291265)30:0.000120563)30;"); - stTree *tree1, *tree2; - stPhylogeny_nni(stTree_findChild(geneTree, "branch"), &tree1, &tree2); - CuAssertTrue(testCase, !stTree_equals(geneTree, tree1)); - CuAssertTrue(testCase, !stTree_equals(geneTree, tree2)); - // Truth set. OK, these are rooted and have branch lengths, so - // it's concievable this test could fail without the method being - // wrong. But right now we have no way to test if the unrooted - // topology is equal. - stTree *neighbor1 = stTree_parseNewickString("(NZOHlLtJ.chr9_87081620_87115187|0|16656-16694.30:0.000120563,((C57B6NJ.chr9_90403979_90439438|18548-18586.29:0.00113208,(C57B6NJ.chr1_3987551_4018377|20930-20968.30:0.0001,(C57B6J.9_87174839_87208406|16656-16694.30:0.0001,C57B6NJ.chr9_90403979_90439438|16656-16694.27:0.0001)27:0.00132877)branch:0.0554717)27:0.00291265,C57B6NJ.chr1_3987551_4018377|15210-15248.30:0.0001)30:0.000120563)30;"); - stTree *neighbor2 = stTree_parseNewickString("(NZOHlLtJ.chr9_87081620_87115187|0|16656-16694.30:0.000120563,((C57B6J.9_87174839_87208406|16656-16694.30:0.0001,C57B6NJ.chr9_90403979_90439438|16656-16694.27:0.0001)27:0.00132877,((C57B6NJ.chr1_3987551_4018377|20930-20968.30:0.0001,C57B6NJ.chr9_90403979_90439438|18548-18586.29:0.00113208)branch:0.0554717,C57B6NJ.chr1_3987551_4018377|15210-15248.30:0.0001)27:0.00291265)30:0.000120563)30;"); - CuAssertTrue(testCase, stTree_equals(tree1, neighbor1) || stTree_equals(tree1, neighbor2)); - CuAssertTrue(testCase, stTree_equals(tree2, neighbor1) || stTree_equals(tree2, neighbor2)); - CuAssertTrue(testCase, !stTree_equals(tree1, tree2)); - - stTree_destruct(geneTree); - stTree_destruct(tree1); - stTree_destruct(tree2); - stTree_destruct(neighbor1); - stTree_destruct(neighbor2); -} - -static void testStPhylogeny_getSplits(CuTest *testCase) { - // Check against the example given in Bandelt and Dress, 1992. - double distanceArray[7][7] = { - { 0, 4, 5, 7, 13, 8, 6}, - { 4, 0, 1, 3, 9, 12, 10}, - { 5, 1, 0, 2, 8, 13, 11}, - { 7, 3, 2, 0, 6, 11, 13}, - {13, 9, 8, 6, 0, 5, 7}, - { 8, 12, 13, 11, 5, 0, 2}, - { 6, 10, 11, 13, 7, 2, 0} - }; - stMatrix *distanceMatrix = stMatrix_construct(7, 7); - for (int64_t i = 0; i < 7; i++) { - for (int64_t j = 0; j < 7; j++) { - *stMatrix_getCell(distanceMatrix, i, j) = distanceArray[i][j]; - } - } - stList *splits = stPhylogeny_getSplits(distanceMatrix, true); - CuAssertIntEquals(testCase, 4, stList_length(splits)); - - // Check the individual splits. We don't check the actual indices - // within the splits, because that would be very long, and it - // would be very hard to be wrong about the content of the - // splits without the isolation index / split sizes being wrong as - // well. - stSplit *split1 = stList_get(splits, 0); - CuAssertDblEquals(testCase, 6.0, split1->isolationIndex, 0.01); - CuAssertTrue(testCase, stList_length(split1->leftSplit) == 3 || stList_length(split1->rightSplit) == 3); - CuAssertTrue(testCase, stList_length(split1->leftSplit) == 4 || stList_length(split1->rightSplit) == 4); - - stSplit *split2 = stList_get(splits, 1); - CuAssertDblEquals(testCase, 4.0, split2->isolationIndex, 0.01); - CuAssertTrue(testCase, stList_length(split2->leftSplit) == 3 || stList_length(split2->rightSplit) == 3); - CuAssertTrue(testCase, stList_length(split2->leftSplit) == 4 || stList_length(split2->rightSplit) == 4); - - stSplit *split3 = stList_get(splits, 2); - CuAssertDblEquals(testCase, 2.0, split3->isolationIndex, 0.01); - CuAssertTrue(testCase, stList_length(split3->leftSplit) == 3 || stList_length(split3->rightSplit) == 3); - CuAssertTrue(testCase, stList_length(split3->leftSplit) == 4 || stList_length(split3->rightSplit) == 4); - - stSplit *split4 = stList_get(splits, 3); - CuAssertDblEquals(testCase, 1.0, split4->isolationIndex, 0.01); - CuAssertTrue(testCase, stList_length(split4->leftSplit) == 3 || stList_length(split4->rightSplit) == 3); - CuAssertTrue(testCase, stList_length(split4->leftSplit) == 4 || stList_length(split4->rightSplit) == 4); - - stMatrix_destruct(distanceMatrix); - stList_destruct(splits); -} - -static void testStPhylogeny_greedySplitDecomposition(CuTest *testCase) { - /* - _______________ MOUSE.2 - | - | ________________ MOUSE.0 - | | - | | ________________ RHESUS.0 - | |________________| - |_______________| | ________________ CHIMP.0 - | | |________________| - | | |________________ HUMAN.0 - | | -_| | ________________ CAT.0 - | |________________| - | |________________ DOG.0 - | - | ________________ CAT.2 - |_______________| - | |________________ DOG.2 - | - | ________________ CHIMP.2 - | | - |_______________|________________ HUMAN.2 - | - |________________ RHESUS.2 - */ - // array ordering: ['CHIMP.0', 'CAT.2', 'CHIMP.2', 'CAT.0', 'HUMAN.2', 'HUMAN.0', 'RHESUS.0', 'RHESUS.2', 'MOUSE.0', 'DOG.0', 'MOUSE.2', 'DOG.2'] - double distanceArray[12][12] = { - { 0.0, 0.225, 0.22, 0.06, 0.215, 0.0, 0.015, 0.21, 0.075, 0.06, 0.235, 0.255,}, - { 0.225, 0.0, 0.05, 0.22, 0.045, 0.225, 0.23, 0.04, 0.235, 0.225, 0.09, 0.03, }, - { 0.22, 0.05, 0.0, 0.215, 0.015, 0.22, 0.225, 0.01, 0.23, 0.22, 0.08, 0.08, }, - { 0.06, 0.22, 0.215, 0.0, 0.21, 0.06, 0.07, 0.205, 0.07, 0.02, 0.24, 0.25, }, - { 0.215, 0.045, 0.015, 0.21, 0.0, 0.215, 0.22, 0.005, 0.225, 0.215, 0.075, 0.075,}, - { 0.0, 0.225, 0.22, 0.06, 0.215, 0.0, 0.015, 0.21, 0.075, 0.06, 0.235, 0.255,}, - { 0.015, 0.23, 0.225, 0.07, 0.22, 0.015, 0.0, 0.215, 0.085, 0.07, 0.24, 0.26, }, - { 0.21, 0.04, 0.01, 0.205, 0.005, 0.21, 0.215, 0.0, 0.22, 0.21, 0.07, 0.07, }, - { 0.075, 0.235, 0.23, 0.07, 0.225, 0.075, 0.085, 0.22, 0.0, 0.075, 0.255, 0.265,}, - { 0.06, 0.225, 0.22, 0.02, 0.215, 0.06, 0.07, 0.21, 0.075, 0.0, 0.245, 0.255,}, - { 0.235, 0.09, 0.08, 0.24, 0.075, 0.235, 0.24, 0.07, 0.255, 0.245, 0.0, 0.115,}, - { 0.255, 0.03, 0.08, 0.25, 0.075, 0.255, 0.26, 0.07, 0.265, 0.255, 0.115, 0.0 } - }; - stMatrix *distanceMatrix = stMatrix_construct(12, 12); - for (int64_t i = 0; i < 12; i++) { - for (int64_t j = 0; j < 12; j++) { - *stMatrix_getCell(distanceMatrix, i, j) = distanceArray[i][j]; - } - } - - stTree *tree = stPhylogeny_greedySplitDecomposition(distanceMatrix, false); - stTree *mouse2 = stTree_findChild(tree, "10"); - stTree *rooted = stTree_reRoot(mouse2, 0.0); - char *newick = stTree_getNewickTreeString(rooted); - CuAssertStrEquals(testCase, "(10:0,((1:1,11:1):1,(2:1,4:1,7:1):1,(8:1,(6:1,(0:1,5:1):1):1,(3:1,9:1):1):1):1);", newick); - free(newick); - stMatrix_destruct(distanceMatrix); - stTree_destruct(rooted); - stPhylogenyInfo_destructOnTree(tree); - stTree_destruct(tree); -} - -static void testStPhylogeny_getLinkedSpeciesTree(CuTest *testCase) { - // Hackily including the definition here, so I don't have to - // create a whole stPhylogeny_private.h and worry about where it - // gets included. Bad practice. - stTree *getLinkedSpeciesTree(stTree *speciesTree, stTree *polytomy, stHash **speciesToNumGenes); - stTree *speciesTree = stTree_parseNewickString("(((a1,(a2.1,a2.2)a2)a,b)e,((c1, c2)c,(d1, d2)d)f)g;"); - stTree *polytomy = stTree_parseNewickString("(a-1,a-2,a-3,a-4,b-1,b-2,c-1,e-1)G;"); - stHash *leafToSpecies = buildLeafToSpeciesUsingDashSeparator(polytomy, speciesTree); - stPhylogeny_reconcileAtMostBinary(polytomy, leafToSpecies, false); - stHash *speciesToNumGenes; - stTree *linkedSpeciesTree = getLinkedSpeciesTree(speciesTree, polytomy, &speciesToNumGenes); - char *newick = stTree_getNewickTreeString(linkedSpeciesTree); - CuAssertStrEquals(testCase, "((a,b)e,(c,d)f)g;", newick); - CuAssertIntEquals(testCase, 4, *((int64_t *) stHash_search(speciesToNumGenes, stTree_findChild(linkedSpeciesTree, "a")))); - CuAssertIntEquals(testCase, 2, *((int64_t *) stHash_search(speciesToNumGenes, stTree_findChild(linkedSpeciesTree, "b")))); - CuAssertIntEquals(testCase, 1, *((int64_t *) stHash_search(speciesToNumGenes, stTree_findChild(linkedSpeciesTree, "c")))); - CuAssertIntEquals(testCase, 1, *((int64_t *) stHash_search(speciesToNumGenes, stTree_findChild(linkedSpeciesTree, "e")))); - free(newick); - stTree_destruct(linkedSpeciesTree); - stHash_destruct(speciesToNumGenes); - stHash_destruct(leafToSpecies); - stPhylogenyInfo_destructOnTree(polytomy); - stTree_destruct(polytomy); - stTree_destruct(speciesTree); -} - -static void testStPhylogeny_reconciliationCostAtMostBinary_polytomies(CuTest *testCase) { - stTree *speciesTree = stTree_parseNewickString("(((a1,(a2.1,a2.2)a2)a,b)e,((c1, c2)c,(d1, d2)d)f)g;"); - stTree *polytomy = stTree_parseNewickString("(a-1,a-2,a-3,a-4,b-1,b-2,c-1,e-1)G;"); - stHash *leafToSpecies = buildLeafToSpeciesUsingDashSeparator(polytomy, speciesTree); - stPhylogeny_reconcileAtMostBinary(polytomy, leafToSpecies, false); - int64_t dups = 0, losses = 0; - stPhylogeny_reconciliationCostAtMostBinary(polytomy, &dups, &losses); - CuAssertIntEquals(testCase, 1, losses); - CuAssertIntEquals(testCase, 4, dups); - - stHash_destruct(leafToSpecies); - stPhylogenyInfo_destructOnTree(polytomy); - stTree_destruct(polytomy); - stTree_destruct(speciesTree); -} - -static void testStPhylogeny_applyJukesCantorCorrection(CuTest *testCase) { - double distanceArray[6][6] = { - { 0.0, 0.225, 0.22, 0.745, 0.76, 0.0 }, - { 0.225, 0.0, 0.05, 0.22, 0.045, 0.225 }, - { 0.22, 0.05, 0.0, 0.215, 0.015, 0.22 }, - { 0.745, 0.22, 0.215, 0.0, 0.21, 0.06 }, - { 0.76, 0.045, 0.015, 0.21, 0.0, 0.215 }, - { 0.0, 0.225, 0.22, 0.06, 0.215, 0.0 }, - }; - stMatrix *distanceMatrix = stMatrix_construct(6, 6); - for (int64_t i = 0; i < 6; i++) { - for (int64_t j = 0; j < 6; j++) { - *stMatrix_getCell(distanceMatrix, i, j) = distanceArray[i][j]; - } - } - - stPhylogeny_applyJukesCantorCorrection(distanceMatrix); - CuAssertDblEquals(testCase, 3.7579, *stMatrix_getCell(distanceMatrix, 3, 0), 0.001); - CuAssertDblEquals(testCase, 0.0625, *stMatrix_getCell(distanceMatrix, 3, 5), 0.001); - // Check that values over 0.75 don't return NaN or infinity. - CuAssertTrue(testCase, isnormal(*stMatrix_getCell(distanceMatrix, 4, 0))); - - stMatrix_destruct(distanceMatrix); -} - -// Large tree that takes forever if the reconciliation algorithm isn't -// linear time. This is sort of a hacky way to test that the -// reconciliation algorithm stays linear. The test won't fail if it is -// O(n^2) or exponential, but it will take 30+ mins. -static void testStPhylogeny_reconcileLargeTree_shouldBeFast(CuTest *testCase) { - stTree *geneTree = stTree_parseNewickString("(((0:0.0338606,(24:0,(((((25:0,28:0.00688078):0,26:0):0,27:0):0,29:0):0.0103492,48:0.0131733):0):0.00135617):0,(49:0.00344003,51:0.0607045):0):0.0036751,((((((((((((((((((((((1:0,((15:0,(((((((((((((((((30:0,31:0):0,32:0):0,33:0):0,34:0):0,35:0):0,36:0):0,37:0):0,38:0):0,39:0):0,40:0):0,41:0):0,42:0):0,43:0):0,44:0):0,46:0):0,47:0):0.00485278,45:0.00495128):0.0185071):0.00778827,16:0):0):0,2:0):0,3:0):0,4:0):0,5:0):0,6:0):0,7:0):0,8:0):0,9:0):0,10:0):0,11:0):0,12:0):0,13:0):0,14:0):0,17:0):0,18:0):0,19:0):0,20:0):0,21:0):0,22:0):0,23:0):0.00330033,50:0):0.0036751);"); - stPhylogeny_addStIndexedTreeInfo(geneTree); - int64_t numSpecies = 0; - stTree *speciesTree = getRandomBinaryTree(st_randomInt64(2, 7), &numSpecies); - stPhylogeny_addStIndexedTreeInfo(speciesTree); - // Assign genes to random species. - stHash *leafToSpecies = stHash_construct(); - for(int64_t i = 0; i < 52; i++) { - stTree *gene = stPhylogeny_getLeafByIndex(geneTree, i); - stTree *species = stPhylogeny_getLeafByIndex(speciesTree, st_randomInt64(0, numSpecies)); - stHash_insert(leafToSpecies, gene, species); - } - - stPhylogeny_reconcileAtMostBinary(geneTree, leafToSpecies, false); - stPhylogenyInfo_destructOnTree(geneTree); - stTree_destruct(geneTree); - stPhylogenyInfo_destructOnTree(speciesTree); - stTree_destruct(speciesTree); - stHash_destruct(leafToSpecies); -} - -CuSuite* sonLib_stPhylogenyTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, testStPhylogeny_reconciliationCostAtMostBinary_polytomies); - SUITE_ADD_TEST(suite, testStPhylogeny_getLinkedSpeciesTree); - SUITE_ADD_TEST(suite, testStPhylogeny_greedySplitDecomposition); - SUITE_ADD_TEST(suite, testStPhylogeny_getSplits); - SUITE_ADD_TEST(suite, testStPhylogeny_nni); - SUITE_ADD_TEST(suite, testJoinCosts_random); - SUITE_ADD_TEST(suite, testStPhylogeny_reconcileAtMostBinary_degree2Nodes); - SUITE_ADD_TEST(suite, testSimpleNeighborJoin); - SUITE_ADD_TEST(suite, testSimpleBootstrapPartitionScoring); - SUITE_ADD_TEST(suite, testSimpleBootstrapReconciliationScoring); - SUITE_ADD_TEST(suite, testRandomNeighborJoin); - SUITE_ADD_TEST(suite, testRandomBootstraps); - SUITE_ADD_TEST(suite, testSimpleJoinCosts); - SUITE_ADD_TEST(suite, testGuidedNeighborJoiningReducesToNeighborJoining); - SUITE_ADD_TEST(suite, testGuidedNeighborJoiningLowersReconCost); - SUITE_ADD_TEST(suite, testStPhylogeny_rootByReconciliationAtMostBinary_simpleTests); - SUITE_ADD_TEST(suite, testStPhylogeny_rootByReconciliationAtMostBinary_random); - SUITE_ADD_TEST(suite, testStPhylogeny_reconcileNonBinary); - SUITE_ADD_TEST(suite, testStPhylogeny_applyJukesCantorCorrection); - SUITE_ADD_TEST(suite, testStPhylogeny_reconcileLargeTree_shouldBeFast); - - (void) testStPhylogeny_reconciliationCostAtMostBinary_polytomies; - (void) testStPhylogeny_getLinkedSpeciesTree; - (void) testStPhylogeny_greedySplitDecomposition; - (void) testStPhylogeny_getSplits; - (void) testStPhylogeny_nni; - (void) testJoinCosts_random; - (void) testStPhylogeny_reconcileAtMostBinary_degree2Nodes; - (void) testSimpleNeighborJoin; - (void) testSimpleBootstrapPartitionScoring; - (void) testSimpleBootstrapReconciliationScoring; - (void) testRandomNeighborJoin; - (void) testRandomBootstraps; - (void) testSimpleJoinCosts; - (void) testGuidedNeighborJoiningReducesToNeighborJoining; - (void) testGuidedNeighborJoiningLowersReconCost; - (void) testStPhylogeny_rootByReconciliationAtMostBinary_simpleTests; - (void) testStPhylogeny_rootByReconciliationAtMostBinary_random; - (void) testStPhylogeny_reconcileNonBinary; - return suite; -} diff --git a/C/tests/stThreadPoolTest.c b/C/tests/stThreadPoolTest.c deleted file mode 100644 index 8a456a6..0000000 --- a/C/tests/stThreadPoolTest.c +++ /dev/null @@ -1,86 +0,0 @@ -#include "CuTest.h" -#include "sonLib.h" - -// Test sorting a few sublists into a larger list to try to catch out -// any race conditions. -static stList *sorted; - -static stList *sortSubList(stList *input) { - stList_sort(input, (int (*)(const void *, const void *)) stIntTuple_cmpFn); - return input; -} - -// Ideally this would be a true merge sort. But since this is just to -// test for race conditions we do something slower. -static void insertSubList(stList *result) { - int64_t result_i = 0, sorted_i = 0; - stList *newSorted = stList_construct(); - while (result_i != stList_length(result) || sorted_i != stList_length(sorted)) { - if (result_i != stList_length(result) && (sorted_i == stList_length(sorted) || stIntTuple_cmpFn(stList_get(result, result_i), stList_get(sorted, sorted_i)) == -1)) { - stList_append(newSorted, stList_get(result, result_i)); - result_i++; - } else if (sorted_i != stList_length(sorted)) { - stList_append(newSorted, stList_get(sorted, sorted_i)); - sorted_i++; - } - } - - stList_destruct(sorted); - sorted = newSorted; -} - -static void testStThreadPoolSort(CuTest *testCase) { - for (int64_t testNum = 0; testNum < 3; testNum++) { - // Create two lists, one containing a bunch of random numbers - // and the other containing a bunch of sublists that contain - // the same numbers, in aggregate. - stList *truth = stList_construct(); - sorted = stList_construct(); - // This list and its sublists are the only ones that own the - // stIntTuples. - stList *lists = stList_construct3(0, (void (*)(void *)) stList_destruct); - int64_t numSubLists = st_randomInt64(1, 100); - for (int64_t i = 0; i < numSubLists; i++) { - stList *subList = stList_construct3(0, (void (*)(void *)) stIntTuple_destruct); - int64_t numNums = st_randomInt64(0, 50000); - for (int64_t j = 0; j < numNums; j++) { - stList_append(subList, stIntTuple_construct1(st_randomInt64(-100000, 100000))); - } - stList_appendAll(truth, subList); - stList_append(lists, subList); - } - - // First sort our list. - stList_sort(truth, (int (*)(const void *, const void *)) stIntTuple_cmpFn); - - // Now create a bunch of threads and ask them to sort theirs. - stThreadPool *threadPool = stThreadPool_construct(st_randomInt64(1, 6), - (void *(*)(void *)) sortSubList, - (void (*)(void *)) insertSubList); - for (int64_t i = 0; i < stList_length(lists); i++) { - stThreadPool_push(threadPool, stList_get(lists, i)); - } - - // Wait for the process to complete. - stThreadPool_wait(threadPool); - CuAssertTrue(testCase, stThreadPool_done(threadPool)); - - CuAssertIntEquals(testCase, stList_length(truth), stList_length(sorted)); - for (int64_t i = 0; i < stList_length(sorted); i++) { - CuAssertIntEquals(testCase, - stIntTuple_get(stList_get(sorted, i), 0), - stIntTuple_get(stList_get(truth, i), 0)); - } - - stThreadPool_destruct(threadPool); - stList_destruct(sorted); - stList_destruct(lists); - stList_destruct(truth); - } -} - -CuSuite *sonLib_stThreadPoolTestSuite(void) { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, testStThreadPoolSort); - return suite; -} diff --git a/C/tests/stUnionFindTest.c b/C/tests/stUnionFindTest.c deleted file mode 100644 index c39826d..0000000 --- a/C/tests/stUnionFindTest.c +++ /dev/null @@ -1,103 +0,0 @@ -#include "CuTest.h" -#include "sonLib.h" - -// Simple static test. -static void stUnionFind_staticTest(CuTest *testCase) { - stUnionFind *unionFind = stUnionFind_construct(); - stUnionFind_add(unionFind, (void *) 1); - stUnionFind_add(unionFind, (void *) 2); - stUnionFind_add(unionFind, (void *) 3); - stUnionFind_add(unionFind, (void *) 4); - stUnionFind_add(unionFind, (void *) 5); - stUnionFind_add(unionFind, (void *) 6); - - CuAssertTrue(testCase, - stUnionFind_find(unionFind, (void *) 1) != stUnionFind_find(unionFind, (void *) 3)); - stUnionFind_union(unionFind, (void *) 1, (void *) 3); - CuAssertTrue(testCase, - stUnionFind_find(unionFind, (void *) 1) == stUnionFind_find(unionFind, (void *) 3)); - - CuAssertTrue(testCase, - stUnionFind_find(unionFind, (void *) 2) != stUnionFind_find(unionFind, (void *) 5)); - stUnionFind_union(unionFind, (void *) 2, (void *) 5); - CuAssertTrue(testCase, - stUnionFind_find(unionFind, (void *) 2) == stUnionFind_find(unionFind, (void *) 5)); - stUnionFind_union(unionFind, (void *) 4, (void *) 1); - CuAssertTrue(testCase, - stUnionFind_find(unionFind, (void *) 3) == stUnionFind_find(unionFind, (void *) 4)); - stUnionFind_union(unionFind, (void *) 1, (void *) 3); - stUnionFind_union(unionFind, (void *) 1, (void *) 5); - stUnionFind_union(unionFind, (void *) 3, (void *) 5); - - stUnionFindIt *it = stUnionFind_getIterator(unionFind); - stSet *setOne = stUnionFindIt_getNext(it); - stSet *setTwo = stUnionFindIt_getNext(it); - CuAssertTrue(testCase, stUnionFindIt_getNext(it) == NULL); - CuAssertTrue(testCase, stSet_size(setOne) == 5 || stSet_size(setTwo) == 5); - CuAssertTrue(testCase, stSet_size(setOne) == 1 || stSet_size(setTwo) == 1); - stUnionFind_destructIterator(it); - stUnionFind_destruct(unionFind); -} - -// Compare stUnionFind and the already battle-tested stConnectivity to -// ensure correctness. -static void stUnionFind_randomTest(CuTest *testCase) { - for (int64_t iteration = 0; iteration < 100; iteration++) { - stUnionFind *unionFind = stUnionFind_construct(); - stConnectivity *connectivity = stConnectivity_construct(); - int64_t numNodes = 2000; - for (int64_t i = 1; i <= numNodes; i++) { - stUnionFind_add(unionFind, (void *) i); - stConnectivity_addNode(connectivity, (void *) i); - } - - int64_t numTests = numNodes * 2; - while (numTests > 0) { - int64_t i = st_randomInt64(1, numNodes + 1); - int64_t j = st_randomInt64(1, numNodes + 1); - bool connectedInUnionFind = stUnionFind_find(unionFind, (void *) i) == stUnionFind_find(unionFind, (void *) j); - bool connectedInConnectivity = stConnectivity_connected(connectivity, (void *) i, (void *) j); - CuAssertIntEquals(testCase, connectedInConnectivity, connectedInUnionFind); - - stUnionFind_union(unionFind, (void *) i, (void *) j); - if (i != j) { - // stConnectivity requires i != j. Not adding the - // self-loop to stConnectivity is OK when i == j, - // because obviously self-loops cannot change the - // connected components. - stConnectivity_addEdge(connectivity, (void *) i, (void *) j); - } - - CuAssertTrue(testCase, stUnionFind_find(unionFind, (void *) i) == stUnionFind_find(unionFind, (void *) j)); - numTests--; - } - - // Check that the total number of components between the two are equal. - int64_t numConnectivityComponents = 0; - stConnectedComponentIterator *connIt = stConnectivity_getConnectedComponentIterator(connectivity); - stConnectedComponent *connComponent; - while ((connComponent = stConnectedComponentIterator_getNext(connIt)) != NULL) { - numConnectivityComponents++; - } - stConnectedComponentIterator_destruct(connIt); - - int64_t numUnionFindComponents = 0; - stUnionFindIt *unionFindIt = stUnionFind_getIterator(unionFind); - stSet *unionFindComponent; - while ((unionFindComponent = stUnionFindIt_getNext(unionFindIt)) != NULL) { - numUnionFindComponents++; - } - stUnionFind_destructIterator(unionFindIt); - CuAssertIntEquals(testCase, numConnectivityComponents, numUnionFindComponents); - - stUnionFind_destruct(unionFind); - stConnectivity_destruct(connectivity); - } -} - -CuSuite *sonLib_stUnionFindTestSuite(void) { - CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, stUnionFind_staticTest); - SUITE_ADD_TEST(suite, stUnionFind_randomTest); - return suite; -} diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index e031899..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2009-2014 by Benedict Paten (benedictpaten@gmail.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/Makefile b/Makefile deleted file mode 100644 index 35eb8b5..0000000 --- a/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -include include.mk -binPath = ./bin - -.PHONY: all clean cP cP.clean externalToolsP.clean test - -all : cP ${binPath}/sonLib_daemonize.py - -clean : cP.clean externalToolsP.clean - rm -f ${binPath}/sonLib_daemonize.py - -cP: externalToolsP - cd C && $(MAKE) all - -externalToolsP: - cd externalTools && $(MAKE) all - -cP.clean : - cd C && $(MAKE) clean - -externalToolsP.clean : - cd externalTools && $(MAKE) clean - -test : all - PYTHONPATH=.. PATH=../../bin:$$PATH python allTests.py --testLength=SHORT --logLevel=CRITICAL - -${binPath}/sonLib_daemonize.py : sonLib_daemonize.py cP - cp sonLib_daemonize.py ${binPath}/sonLib_daemonize.py - chmod +x ${binPath}/sonLib_daemonize.py diff --git a/README.md b/README.md index bc43a06..c3fc504 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,8 @@ # sonLib **sonLib** is a compact C/Python library for sequence analysis in bioinformatics. -(c) 2006 - 2012 The Author(s). See LICENSE.txt for details. +## New Location -## Author -[Benedict Paten](https://github.com/benedictpaten/) +The sonLib repository is now located at +[https://github.com/ComparativeGenomicsToolkit/sonLib](https://github.com/ComparativeGenomicsToolkit/sonLib) -## Description -For basic data-structures in C it contains: - - * array lists (automatically resizing) - * hashes - * sets (backed by hashes) - * sorted sets (backed by an AVL tree) - * containers (for putting primitives into the above data-structures) - * better string functions - * simple exception mechanism - * logging functions - -For bioinformatic data-structures it contains (or will contain): - - * Fasta I/O functions - * MAF I/O functions - * Newick tree I/O functions - -For more details see the Full README in doc/README diff --git a/__init__.py b/__init__.py deleted file mode 100644 index 9d39579..0000000 --- a/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt diff --git a/allTests.py b/allTests.py deleted file mode 100644 index 04272fb..0000000 --- a/allTests.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt -import unittest - -import bioioTest -import cigarsTest -import treeTest -import kvdbTest -import socket -try: - import networkx as NX - networkx_installed = True - import nxtreeTest - import nxnewickTest -except ImportError: - networkx_installed = False - -from sonLib.bioio import system -from sonLib.bioio import parseSuiteTestOptions -from sonLib.bioio import getLogLevelString - - -class TestCase(unittest.TestCase): - def testSonLibCTests(self): - """Run m,ost the sonLib CuTests, fail if any of them fail. - """ - system("sonLibTests %s" % getLogLevelString()) - -def allSuites(): - bioioSuite = unittest.makeSuite(bioioTest.TestCase, 'test') - cigarsSuite = unittest.makeSuite(cigarsTest.TestCase, 'test') - treeSuite = unittest.makeSuite(treeTest.TestCase, 'test') - kvdbSuite = unittest.makeSuite(kvdbTest.TestCase, 'test') - cuTestsSuite = unittest.makeSuite(TestCase, 'test') - if not networkx_installed: - allTests = unittest.TestSuite((bioioSuite, cigarsSuite, treeSuite, kvdbSuite, cuTestsSuite)) - else: - nxtreeSuite = unittest.makeSuite(nxtreeTest.TestCase, 'test') - nxnewickSuite = unittest.makeSuite(nxnewickTest.TestCase, 'test') - allTests = unittest.TestSuite((bioioSuite, cigarsSuite, treeSuite, kvdbSuite, cuTestsSuite, - nxtreeSuite, nxnewickSuite)) - return allTests - -def main(): - parseSuiteTestOptions() - - suite = allSuites() - runner = unittest.TextTestRunner() - i = runner.run(suite) - return len(i.failures) + len(i.errors) - -if __name__ == '__main__': - import sys - sys.exit(main()) diff --git a/bioio.py b/bioio.py deleted file mode 100644 index 3b1070a..0000000 --- a/bioio.py +++ /dev/null @@ -1,1316 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt - -import sys -import os -import re -import logging -import resource -import logging.handlers -import tempfile -import random -import math -import shutil -from argparse import ArgumentParser -from optparse import OptionParser, OptionContainer, OptionGroup -from tree import BinaryTree -from misc import close -import subprocess -import array -import string -import xml.etree.cElementTree as ET -from xml.dom import minidom # For making stuff pretty - -DEFAULT_DISTANCE = 0.001 - -######################################################### -######################################################### -######################################################### -#global logging settings / log functions -######################################################### -######################################################### -######################################################### - -loggingFormatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)s %(message)s') - -def __setDefaultLogger(): - l = logging.getLogger() - for handler in l.handlers: #Do not add a duplicate handler unless needed - if handler.stream == sys.stderr: - return l - handler = logging.StreamHandler(sys.stderr) - l.addHandler(handler) - l.setLevel(logging.CRITICAL) - return l - -logger = __setDefaultLogger() -logLevelString = "CRITICAL" - -def redirectLoggerStreamHandlers(oldStream, newStream): - """Redirect the stream of a stream handler to a different stream - """ - for handler in list(logger.handlers): #Remove old handlers - if handler.stream == oldStream: - handler.close() - logger.removeHandler(handler) - for handler in logger.handlers: #Do not add a duplicate handler - if handler.stream == newStream: - return - logger.addHandler(logging.StreamHandler(newStream)) - -def getLogLevelString(): - return logLevelString - -__loggingFiles = [] -def addLoggingFileHandler(fileName, rotatingLogging=False): - if fileName in __loggingFiles: - return - __loggingFiles.append(fileName) - if rotatingLogging: - handler = logging.handlers.RotatingFileHandler(fileName, maxBytes=1000000, backupCount=1) - else: - handler = logging.FileHandler(fileName) - logger.addHandler(handler) - return handler - -def setLogLevel(logLevel): - logLevel = logLevel.upper() - assert logLevel in [ "OFF", "CRITICAL", "INFO", "DEBUG" ] #Log level must be one of these strings. - global logLevelString - logLevelString = logLevel - if logLevel == "OFF": - logger.setLevel(logging.FATAL) - elif logLevel == "INFO": - logger.setLevel(logging.INFO) - elif logLevel == "DEBUG": - logger.setLevel(logging.DEBUG) - elif logLevel == "CRITICAL": - logger.setLevel(logging.CRITICAL) - -def logFile(fileName, printFunction=logger.info): - """Writes out a formatted version of the given log file - """ - printFunction("Reporting file: %s" % fileName) - shortName = fileName.split("/")[-1] - fileHandle = open(fileName, 'r') - line = fileHandle.readline() - while line != '': - if line[-1] == '\n': - line = line[:-1] - printFunction("%s:\t%s" % (shortName, line)) - line = fileHandle.readline() - fileHandle.close() - -def addLoggingOptions(parser): - # Wrapper function that allows jobTree to be used with both the optparse and - # argparse option parsing modules - if isinstance(parser, OptionContainer): - group = OptionGroup(parser, "Logging options", - "Options that control logging") - _addLoggingOptions(group.add_option) - parser.add_option_group(group) - elif isinstance(parser, ArgumentParser): - group = parser.add_argument_group("Logging Options", - "Options that control logging") - _addLoggingOptions(group.add_argument) - else: - raise RuntimeError("Unanticipated class passed to " - "addLoggingOptions(), %s. Expecting " - "Either optparse.OptionParser or " - "argparse.ArgumentParser" % parser.__class__) - -def _addLoggingOptions(addOptionFn): - """Adds logging options - """ - ################################################## - # BEFORE YOU ADD OR REMOVE OPTIONS TO THIS FUNCTION, KNOW THAT - # YOU MAY ONLY USE VARIABLES ACCEPTED BY BOTH optparse AND argparse - # FOR EXAMPLE, YOU MAY NOT USE default=%default OR default=%(default)s - ################################################## - addOptionFn("--logOff", dest="logOff", action="store_true", default=False, - help="Turn off logging. (default is CRITICAL)") - addOptionFn( - "--logInfo", dest="logInfo", action="store_true", default=False, - help="Turn on logging at INFO level. (default is CRITICAL)") - addOptionFn( - "--logDebug", dest="logDebug", action="store_true", default=False, - help="Turn on logging at DEBUG level. (default is CRITICAL)") - addOptionFn( - "--logLevel", dest="logLevel", default='CRITICAL', - help=("Log at level (may be either OFF/INFO/DEBUG/CRITICAL). " - "(default is CRITICAL)")) - addOptionFn("--logFile", dest="logFile", help="File to log in") - addOptionFn( - "--rotatingLogging", dest="logRotating", action="store_true", - default=False, help=("Turn on rotating logging, which prevents log " - "files getting too big.")) - -def setLoggingFromOptions(options): - """Sets the logging from a dictionary of name/value options. - """ - #We can now set up the logging info. - if options.logLevel is not None: - setLogLevel(options.logLevel) #Use log level, unless flags are set.. - - if options.logOff: - setLogLevel("OFF") - elif options.logInfo: - setLogLevel("INFO") - elif options.logDebug: - setLogLevel("DEBUG") - - logger.info("Logging set at level: %s" % logLevelString) - - if options.logFile is not None: - addLoggingFileHandler(options.logFile, options.logRotating) - - logger.info("Logging to file: %s" % options.logFile) - - -######################################################### -######################################################### -######################################################### -#system wrapper command -######################################################### -######################################################### -######################################################### - -def system(command): - logger.debug("Running the command: %s" % command) - sts = subprocess.call(command, shell=True, bufsize=-1) - if sts != 0: - raise RuntimeError("Command: %s exited with non-zero status %i" % (command, sts)) - return sts - -def popen(command, tempFile): - """Runs a command and captures standard out in the given temp file. - """ - fileHandle = open(tempFile, 'w') - logger.debug("Running the command: %s" % command) - sts = subprocess.call(command, shell=True, stdout=fileHandle, bufsize=-1) - fileHandle.close() - if sts != 0: - raise RuntimeError("Command: %s exited with non-zero status %i" % (command, sts)) - return sts - -def popenCatch(command, stdinString=None): - """Runs a command and return standard out. - """ - logger.debug("Running the command: %s" % command) - if stdinString != None: - process = subprocess.Popen(command, shell=True, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=-1) - output, nothing = process.communicate(stdinString) - else: - process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=sys.stderr, bufsize=-1) - output, nothing = process.communicate() #process.stdout.read().strip() - sts = process.wait() - if sts != 0: - raise RuntimeError("Command: %s with stdin string '%s' exited with non-zero status %i" % (command, stdinString, sts)) - return output #process.stdout.read().strip() - -def popenPush(command, stdinString=None): - if stdinString == None: - system(command) - else: - process = subprocess.Popen(command, shell=True, - stdin=subprocess.PIPE, bufsize=-1) - process.communicate(stdinString) - sts = process.wait() - if sts != 0: - raise RuntimeError("Command: %s with stdin string '%s' exited with non-zero status %i" % (command, stdinString, sts)) - -def spawnDaemon(command): - """Launches a command as a daemon. It will need to be explicitly killed - """ - return system("sonLib_daemonize.py \'%s\'" % command) - -def getTotalCpuTimeAndMemoryUsage(): - """Gives the total cpu time and memory usage of itself and its children. - """ - me = resource.getrusage(resource.RUSAGE_SELF) - childs = resource.getrusage(resource.RUSAGE_CHILDREN) - totalCpuTime = me.ru_utime+me.ru_stime+childs.ru_utime+childs.ru_stime - totalMemoryUsage = me.ru_maxrss+ me.ru_maxrss - return totalCpuTime, totalMemoryUsage - -def getTotalCpuTime(): - """Gives the total cpu time, including the children. - """ - return getTotalCpuTimeAndMemoryUsage()[0] - -def getTotalMemoryUsage(): - """Gets the amount of memory used by the process and its children. - """ - return getTotalCpuTimeAndMemoryUsage()[1] - -def absSymPath(path): - """like os.path.abspath except it doesn't dereference symlinks - """ - curr_path = os.getcwd() - return os.path.normpath(os.path.join(curr_path, path)) - -######################################################### -######################################################### -######################################################### -#testing settings -######################################################### -######################################################### -######################################################### - -class TestStatus: - ###Global variables used by testing framework to run tests. - TEST_SHORT = 0 - TEST_MEDIUM = 1 - TEST_LONG = 2 - TEST_VERY_LONG = 3 - - TEST_STATUS = TEST_SHORT - - SAVE_ERROR_LOCATION = None - - def getTestStatus(): - return TestStatus.TEST_STATUS - getTestStatus = staticmethod(getTestStatus) - - def setTestStatus(status): - assert status in (TestStatus.TEST_SHORT, TestStatus.TEST_MEDIUM, TestStatus.TEST_LONG, TestStatus.TEST_VERY_LONG) - TestStatus.TEST_STATUS = status - setTestStatus = staticmethod(setTestStatus) - - def getSaveErrorLocation(): - """Location to in which to write inputs which created test error. - """ - return TestStatus.SAVE_ERROR_LOCATION - getSaveErrorLocation = staticmethod(getSaveErrorLocation) - - def setSaveErrorLocation(dir): - """Set location in which to write inputs which created test error. - """ - logger.info("Location to save error files in: %s" % dir) - assert os.path.isdir(dir) - TestStatus.SAVE_ERROR_LOCATION = dir - setSaveErrorLocation = staticmethod(setSaveErrorLocation) - - def getTestSetup(shortTestNo=1, mediumTestNo=5, longTestNo=100, veryLongTestNo=0): - if TestStatus.TEST_STATUS == TestStatus.TEST_SHORT: - return shortTestNo - elif TestStatus.TEST_STATUS == TestStatus.TEST_MEDIUM: - return mediumTestNo - elif TestStatus.TEST_STATUS == TestStatus.TEST_LONG: - return longTestNo - else: #Used for long example tests - return veryLongTestNo - getTestSetup = staticmethod(getTestSetup) - - def getPathToDataSets(): - """This method is used to store the location of - the path where all the data sets used by tests for analysis are kept. - These are not kept in the distrbution itself for reasons of size. - """ - assert "SON_TRACE_DATASETS" in os.environ - return os.environ["SON_TRACE_DATASETS"] - getPathToDataSets = staticmethod(getPathToDataSets) - -def saveInputs(savedInputsDir, listOfFilesAndDirsToSave): - """Copies the list of files to a directory created in the save inputs dir, - and returns the name of this directory. - """ - logger.info("Saving the inputs: %s to the directory: %s" % (" ".join(listOfFilesAndDirsToSave), savedInputsDir)) - assert os.path.isdir(savedInputsDir) - #savedInputsDir = getTempDirectory(saveInputsDir) - createdFiles = [] - for fileName in listOfFilesAndDirsToSave: - if os.path.isfile(fileName): - copiedFileName = os.path.join(savedInputsDir, os.path.split(fileName)[-1]) - system("cp %s %s" % (fileName, copiedFileName)) - else: - copiedFileName = os.path.join(savedInputsDir, os.path.split(fileName)[-1]) + ".tar" - system("tar -cf %s %s" % (copiedFileName, fileName)) - createdFiles.append(copiedFileName) - return createdFiles - -######################################################### -######################################################### -######################################################### -#options parser functions -######################################################### -######################################################### -######################################################### - -def getBasicOptionParser(usage="usage: %prog [options]", version="%prog 0.1", parser=None): - if parser is None: - parser = OptionParser(usage=usage, version=version) - - addLoggingOptions(parser) - - parser.add_option("--tempDirRoot", dest="tempDirRoot", type="string", - help="Path to where temporary directory containing all temp files are created, by default uses the current working directory as the base.", - default=os.getcwd()) - - return parser - -def parseBasicOptions(parser): - """Setups the standard things from things added by getBasicOptionParser. - """ - (options, args) = parser.parse_args() - - setLoggingFromOptions(options) - - #Set up the temp dir root - if options.tempDirRoot == "None": - options.tempDirRoot = os.getcwd() - - return options, args - -def parseSuiteTestOptions(parser=None): - if parser is None: - parser = getBasicOptionParser() - - parser.add_option("--testLength", dest="testLength", type="string", - help="Control the length of the tests either SHORT/MEDIUM/LONG/VERY_LONG. default=%default", - default="SHORT") - - parser.add_option("--saveError", dest="saveError", type="string", - help="Directory in which to store the inputs of failed tests") - - options, args = parseBasicOptions(parser) - logger.info("Parsed arguments") - - if options.testLength == "SHORT": - TestStatus.setTestStatus(TestStatus.TEST_SHORT) - elif options.testLength == "MEDIUM": - TestStatus.setTestStatus(TestStatus.TEST_MEDIUM) - elif options.testLength == "LONG": - TestStatus.setTestStatus(TestStatus.TEST_LONG) - elif options.testLength == "VERY_LONG": - TestStatus.setTestStatus(TestStatus.TEST_VERY_LONG) - else: - parser.error('Unrecognised option for --testLength, %s. Options are SHORT, MEDIUM, LONG, VERY_LONG.' % - options.testLength) - - if options.saveError is not None: - TestStatus.setSaveErrorLocation(options.saveError) - - return options, args - -def nameValue(name, value, valueType=str, quotes=False): - """Little function to make it easier to make name value strings for commands. - """ - if valueType == bool: - if value: - return "--%s" % name - return "" - if value is None: - return "" - if quotes: - return "--%s '%s'" % (name, valueType(value)) - return "--%s %s" % (name, valueType(value)) - -######################################################### -######################################################### -######################################################### -#temp files -######################################################### -######################################################### -######################################################### - -def getRandomAlphaNumericString(length=10): - """Returns a random alpha numeric string of the given length. - """ - return "".join([ random.choice('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz') for i in xrange(0, length) ]) - -def makeSubDir(dirName): - """Makes a given subdirectory if it doesn't already exist, making sure it us public. - """ - if not os.path.exists(dirName): - os.mkdir(dirName) - os.chmod(dirName, 0777) - return dirName - -def getTempFile(suffix="", rootDir=None): - """Returns a string representing a temporary file, that must be manually deleted - """ - if rootDir is None: - handle, tmpFile = tempfile.mkstemp(suffix) - os.close(handle) - return tmpFile - else: - tmpFile = os.path.join(rootDir, "tmp_" + getRandomAlphaNumericString() + suffix) - open(tmpFile, 'w').close() - os.chmod(tmpFile, 0777) #Ensure everyone has access to the file. - return tmpFile - -def getTempDirectory(rootDir=None): - """ - returns a temporary directory that must be manually deleted. rootDir will be - created if it does not exist. - """ - if rootDir is None: - return tempfile.mkdtemp() - else: - if not os.path.exists(rootDir): - try: - os.makedirs(rootDir) - except OSError: - # Maybe it got created between the test and the makedirs call? - pass - - while True: - # Keep trying names until we find one that doesn't exist. If one - # does exist, don't nest inside it, because someone else may be - # using it for something. - tmpDir = os.path.join(rootDir, "tmp_" + getRandomAlphaNumericString()) - if not os.path.exists(tmpDir): - break - - os.mkdir(tmpDir) - os.chmod(tmpDir, 0777) #Ensure everyone has access to the file. - return tmpDir - -class TempFileTree: - """A hierarchical tree structure for storing directories of files/dirs/ - - The total number of legal files is equal to filesPerDir**levels. - filesPerDer and levels must both be greater than zero. - The rootDir may or may not yet exist (and may or may not be empty), though - if files exist in the dirs of levels 0 ... level-1 then they must be dirs, - which will be indexed the by tempfile tree. - """ - def __init__(self, rootDir, filesPerDir=500, levels=3): - #Do basic checks of input - assert(filesPerDir) >= 1 - assert(levels) >= 1 - if not os.path.isdir(rootDir): - #Make the root dir - os.mkdir(rootDir) - open(os.path.join(rootDir, "lock"), 'w').close() #Add the lock file - - #Basic attributes of system at start up. - self.levelNo = levels - self.filesPerDir = filesPerDir - self.rootDir = rootDir - #Dynamic variables - self.tempDir = rootDir - self.level = 0 - self.filesInDir = 1 - #These two variables will only refer to the existance of this class instance. - self.tempFilesCreated = 0 - self.tempFilesDestroyed = 0 - - currentFiles = self.listFiles() - logger.info("We have setup the temp file tree, it contains %s files currently, \ - %s of the possible total" % \ - (len(currentFiles), len(currentFiles)/math.pow(filesPerDir, levels))) - - def getTempFile(self, suffix="", makeDir=False): - while 1: - #Basic checks for start of loop - assert self.level >= 0 - assert self.level < self.levelNo - assert os.path.isdir(self.tempDir) - #If tempDir contains max file number then: - if self.filesInDir > self.filesPerDir: - #if level number is already 0 raise an exception - if self.level == 0: - raise RuntimeError("We ran out of space to make temp files") - #Remove the lock file - os.remove(os.path.join(self.tempDir, "lock")) - #reduce level number by one, chop off top of tempDir. - self.level -= 1 - self.tempDir = os.path.split(self.tempDir)[0] - self.filesInDir = len(os.listdir(self.tempDir)) - else: - if self.level == self.levelNo-1: - self.filesInDir += 1 - #make temporary file in dir and return it. - if makeDir: - return getTempDirectory(rootDir=self.tempDir) - else: - return getTempFile(suffix=suffix, rootDir=self.tempDir) - else: - #mk new dir, and add to tempDir path, inc the level buy one. - self.tempDir = getTempDirectory(rootDir=self.tempDir) - open(os.path.join(self.tempDir, "lock"), 'w').close() #Add the lock file - self.level += 1 - self.filesInDir = 1 - - def getTempDirectory(self): - return self.getTempFile(makeDir=True) - - def __destroyFile(self, tempFile): - #If not part of the current tempDir, from which files are being created. - baseDir = os.path.split(tempFile)[0] - if baseDir != self.tempDir: - while True: #Now remove any parent dirs that are empty. - try: - os.rmdir(baseDir) - except OSError: - break - baseDir = os.path.split(baseDir)[0] - if baseDir == self.rootDir: - break - - def destroyTempFile(self, tempFile): - """Removes the temporary file in the temp file dir, checking its in the temp file tree. - """ - #Do basic assertions for goodness of the function - assert os.path.isfile(tempFile) - assert os.path.commonprefix((self.rootDir, tempFile)) == self.rootDir #Checks file is part of tree - #Update stats. - self.tempFilesDestroyed += 1 - #Do the actual removal - os.remove(tempFile) - self.__destroyFile(tempFile) - - def destroyTempDir(self, tempDir): - """Removes a temporary directory in the temp file dir, checking its in the temp file tree. - The dir will be removed regardless of if it is empty. - """ - #Do basic assertions for goodness of the function - assert os.path.isdir(tempDir) - assert os.path.commonprefix((self.rootDir, tempDir)) == self.rootDir #Checks file is part of tree - #Update stats. - self.tempFilesDestroyed += 1 - #Do the actual removal - try: - os.rmdir(tempDir) - except OSError: - shutil.rmtree(tempDir) - #system("rm -rf %s" % tempDir) - self.__destroyFile(tempDir) - - def listFiles(self): - """Gets all files in the temp file tree (which may be dirs). - """ - def fn(dirName, level, files): - if level == self.levelNo-1: - for fileName in os.listdir(dirName): - if fileName != "lock": - absFileName = os.path.join(dirName, fileName) - files.append(absFileName) - else: - for subDir in os.listdir(dirName): - if subDir != "lock": - absDirName = os.path.join(dirName, subDir) - assert os.path.isdir(absDirName) - fn(absDirName, level+1, files) - files = [] - fn(self.rootDir, 0, files) - return files - - def destroyTempFiles(self): - """Destroys all temp temp file hierarchy, getting rid of all files. - """ - os.system("rm -rf %s" % self.rootDir) - logger.debug("Temp files created: %s, temp files actively destroyed: %s" % (self.tempFilesCreated, self.tempFilesDestroyed)) - -######################################################### -######################################################### -######################################################### -#misc input/output functions -######################################################### -######################################################### -######################################################### - -def getNextNonCommentLine(file): - line = file.readline() - while line != '' and line[0] == '#': - line = file.readline() - return line - -def removeNewLine(line): - if line != '' and line[-1] == '\n': - return line[:-1] - return line - -def readFirstLine(inputFile): - i = open(inputFile, 'r') - j = removeNewLine(i.readline()) - i.close() - return j - -def padWord(word, length=25): - if len(word) > length: - return word[:length] - if len(word) < length: - return word + " "*(length-len(word)) - return word - -######################################################### -######################################################### -######################################################### -#Generic file functions -######################################################### -######################################################### -######################################################### - -def catFiles(filesToCat, catFile): - """Cats a bunch of files into one file. Ensures a no more than maxCat files - are concatenated at each step. - """ - if len(filesToCat) == 0: #We must handle this case or the cat call will hang waiting for input - open(catFile, 'w').close() - return - maxCat = 25 - system("cat %s > %s" % (" ".join(filesToCat[:maxCat]), catFile)) - filesToCat = filesToCat[maxCat:] - while len(filesToCat) > 0: - system("cat %s >> %s" % (" ".join(filesToCat[:maxCat]), catFile)) - filesToCat = filesToCat[maxCat:] - -def prettyXml(elem): - """ Return a pretty-printed XML string for the ElementTree Element. - """ - roughString = ET.tostring(elem, "utf-8") - reparsed = minidom.parseString(roughString) - return reparsed.toprettyxml(indent=" ") - -def isNewer(firstFile, secondFile): - """Returns True if the first file was modified more recently than the second file (used os.path.getctime) - """ - assert os.path.exists(firstFile) - assert os.path.exists(secondFile) - return os.path.getctime(firstFile) > os.path.getctime(secondFile) - -######################################################### -######################################################### -######################################################### -#fasta/fastq functions -######################################################### -######################################################### -######################################################### - -def fastaNormaliseHeader(fastaHeader): - """Removes white space which is treated weirdly by many programs. - """ - i = fastaHeader.split() - if len(i) > 0: - return i[0] - return "" - -def fastaDecodeHeader(fastaHeader): - """Decodes the fasta header - """ - return fastaHeader.split("|") - -def fastaEncodeHeader(attributes): - """Decodes the fasta header - """ - for i in attributes: - assert len(str(i).split()) == 1 - return "|".join([ str(i) for i in attributes ]) - -def _getFileHandle(fileHandleOrFile, mode="r"): - if isinstance(fileHandleOrFile, "".__class__): - return open(fileHandleOrFile, mode) - else: - return fileHandleOrFile - -def fastaRead(fileHandleOrFile): - """iteratively yields a sequence for each '>' it encounters, ignores '#' lines - """ - fileHandle = _getFileHandle(fileHandleOrFile) - line = fileHandle.readline() - chars_to_remove = "\n " - valid_chars = {x for x in string.ascii_letters + "-"} - while line != '': - if line[0] == '>': - name = line[1:-1] - line = fileHandle.readline() - seq = array.array('c') - while line != '' and line[0] != '>': - line = line.translate(None, chars_to_remove) - if len(line) > 0 and line[0] != '#': - seq.extend(line) - line = fileHandle.readline() - try: - assert all(x in valid_chars for x in seq) - except AssertionError: - bad_chars = {x for x in seq if x not in valid_chars} - raise RuntimeError("Invalid FASTA character(s) see in fasta sequence: {}".format(bad_chars)) - yield name, seq.tostring() - else: - line = fileHandle.readline() - if isinstance(fileHandleOrFile, "".__class__): - fileHandle.close() - -def fastaWrite(fileHandleOrFile, name, seq, mode="w"): - """Writes out fasta file - """ - fileHandle = _getFileHandle(fileHandleOrFile, mode) - valid_chars = {x for x in string.ascii_letters + "-"} - try: - assert any([isinstance(seq, unicode), isinstance(seq, str)]) - except AssertionError: - raise RuntimeError("Sequence is not unicode or string") - try: - assert all(x in valid_chars for x in seq) - except AssertionError: - bad_chars = {x for x in seq if x not in valid_chars} - raise RuntimeError("Invalid FASTA character(s) see in fasta sequence: {}".format(bad_chars)) - fileHandle.write(">%s\n" % name) - chunkSize = 100 - for i in xrange(0, len(seq), chunkSize): - fileHandle.write("%s\n" % seq[i:i+chunkSize]) - if isinstance(fileHandleOrFile, "".__class__): - fileHandle.close() - -def fastqRead(fileHandleOrFile): - """Reads a fastq file iteratively - """ - fileHandle = _getFileHandle(fileHandleOrFile) - line = fileHandle.readline() - while line != '': - if line[0] == '@': - name = line[1:-1] - seq = fileHandle.readline()[:-1] - plus = fileHandle.readline() - if plus[0] != '+': - raise RuntimeError("Got unexpected line: %s" % plus) - qualValues = [ ord(i) for i in fileHandle.readline()[:-1] ] - if len(seq) != len(qualValues): - logger.critical("Got a mismatch between the number of sequence characters (%s) and number of qual values (%s) for sequence: %s, ignoring returning None" % (len(seq), len(qualValues), name)) - qualValues = None - else: - for i in qualValues: - if i < 33 or i > 126: - raise RuntimeError("Got a qual value out of range %s (range is 33 to 126)" % i) - for i in seq: - #For safety and sanity I only allows roman alphabet characters in fasta sequences. - if not ((i >= 'A' and i <= 'Z') or (i >= 'a' and i <= 'z') or i == '-'): - raise RuntimeError("Invalid FASTQ character, ASCII code = \'%d\', found in input sequence %s" % (ord(i), name)) - yield name, seq, qualValues - line = fileHandle.readline() - if isinstance(fileHandleOrFile, "".__class__): - fileHandle.close() - -def fastqWrite(fileHandleOrFile, name, seq, qualValues, mode="w"): - """Writes out fastq file. If qualValues is None or '*' then prints a '*' instead. - """ - fileHandle = _getFileHandle(fileHandleOrFile, mode) - assert seq.__class__ == "".__class__ - for i in seq: - if not ((i >= 'A' and i <= 'Z') or (i >= 'a' and i <= 'z') or i == '-'): #For safety and sanity I only allows roman alphabet characters in fasta sequences. - raise RuntimeError("Invalid FASTQ character, ASCII code = \'%d\', char = '%s' found in input sequence %s" % (ord(i), i, name)) - if qualValues != None and qualValues != '*': - if len(seq) != len(qualValues): - raise RuntimeError("Got a mismatch between the number of sequence characters (%s) and number of qual values (%s) for sequence: %s " % (len(seq), len(qualValues), name)) - for i in qualValues: - if i < 33 or i > 126: - raise RuntimeError("Got a qual value out of range %s (range is 33 to 126)" % i) - fileHandle.write("@%s\n%s\n+\n%s\n" % (name, seq, "".join([ chr(i) for i in qualValues ]))) - else: - fileHandle.write("@%s\n%s\n+\n*\n" % (name, seq)) - if isinstance(fileHandleOrFile, "".__class__): - fileHandle.close() - -def _getMultiFastaOffsets(fasta): - """Reads in columns of multiple alignment and returns them iteratively - """ - f = open(fasta, 'r') - i = 0 - j = f.read(1) - l = [] - while j != '': - i += 1 - if j == '>': - i += 1 - while f.read(1) != '\n': - i += 1 - l.append(i) - j = f.read(1) - f.close() - return l - -def fastaReadHeaders(fasta): - """Returns a list of fasta header lines, excluding - """ - headers = [] - fileHandle = open(fasta, 'r') - line = fileHandle.readline() - while line != '': - assert line[-1] == '\n' - if line[0] == '>': - headers.append(line[1:-1]) - line = fileHandle.readline() - fileHandle.close() - return headers - -def fastaAlignmentRead(fasta, mapFn=(lambda x : x), l=None): - """ - reads in columns of multiple alignment and returns them iteratively - """ - if l is None: - l = _getMultiFastaOffsets(fasta) - else: - l = l[:] - seqNo = len(l) - for i in xrange(0, seqNo): - j = open(fasta, 'r') - j.seek(l[i]) - l[i] = j - column = [sys.maxint]*seqNo - if seqNo != 0: - while True: - for j in xrange(0, seqNo): - i = l[j].read(1) - while i == '\n': - i = l[j].read(1) - column[j] = i - if column[0] == '>' or column[0] == '': - for j in xrange(1, seqNo): - assert column[j] == '>' or column[j] == '' - break - for j in xrange(1, seqNo): - assert column[j] != '>' and column[j] != '' - column[j] = mapFn(column[j]) - yield column[:] - for i in l: - i.close() - -def fastaAlignmentWrite(columnAlignment, names, seqNo, fastaFile, - filter=lambda x : True): - """ - Writes out column alignment to given file multi-fasta format - """ - fastaFile = open(fastaFile, 'w') - columnAlignment = [ i for i in columnAlignment if filter(i) ] - for seq in xrange(0, seqNo): - fastaFile.write(">%s\n" % names[seq]) - for column in columnAlignment: - fastaFile.write(column[seq]) - fastaFile.write("\n") - fastaFile.close() - -def getRandomSequence(length=500): - """Generates a random name and sequence. - """ - fastaHeader = "" - for i in xrange(int(random.random()*100)): - fastaHeader = fastaHeader + random.choice([ 'A', 'C', '0', '9', ' ', '\t' ]) - return (fastaHeader, \ - "".join([ random.choice([ 'A', 'C', 'T', 'G', 'A', 'C', 'T', 'G', 'A', 'C', 'T', 'G', 'A', 'C', 'T', 'G', 'A', 'C', 'T', 'G', 'N' ]) for i in xrange((int)(random.random() * length))])) - -def _expLength(i=0, prob=0.95): - if random.random() >= prob: - return _expLength(i+1) - return i - -def mutateSequence(seq, distance): - """Mutates the DNA sequence for use in testing. - """ - subProb=distance - inProb=0.05*distance - deProb=0.05*distance - contProb=0.9 - l = [] - bases = [ 'A', 'C', 'T', 'G' ] - i=0 - while i < len(seq): - if random.random() < subProb: - l.append(random.choice(bases)) - else: - l.append(seq[i]) - if random.random() < inProb: - l += getRandomSequence(_expLength(0, contProb))[1] - if random.random() < deProb: - i += int(_expLength(0, contProb)) - i += 1 - return "".join(l) - -def reverseComplement(seq): - seq = list(seq) - seq.reverse() - dNA = { 'A':'T', 'T':'A', 'C':'G', 'G':'C', 'a':'t', 't':'a', 'c':'g', 'g':'c' } - def fn(i): - if i in dNA: - return dNA[i] - return i - return "".join([ fn(i) for i in seq ]) - - -######################################################### -######################################################### -######################################################### -#newick tree functions -######################################################### -######################################################### -######################################################### - -def newickTreeParser(newickTree, defaultDistance=DEFAULT_DISTANCE, \ - sortNonBinaryNodes=False, reportUnaryNodes=False): - """ - lax newick tree parser - """ - newickTree = newickTree.replace("(", " ( ") - newickTree = newickTree.replace(")", " ) ") - newickTree = newickTree.replace(":", " : ") - newickTree = newickTree.replace(";", "") - newickTree = newickTree.replace(",", " , ") - - newickTree = re.compile("[\s]*").split(newickTree) - while "" in newickTree: - newickTree.remove("") - def fn(newickTree, i): - if i[0] < len(newickTree): - if newickTree[i[0]] == ':': - d = float(newickTree[i[0]+1]) - i[0] += 2 - return d - return defaultDistance - def fn2(newickTree, i): - if i[0] < len(newickTree): - j = newickTree[i[0]] - if j != ':' and j != ')' and j != ',': - i[0] += 1 - return j - return None - def fn3(newickTree, i): - if newickTree[i[0]] == '(': - #subTree1 = None - subTreeList = [] - i[0] += 1 - k = [] - while newickTree[i[0]] != ')': - if newickTree[i[0]] == ',': - i[0] += 1 - subTreeList.append(fn3(newickTree, i)) - i[0] += 1 - def cmp(i, j): - if i.distance < j.distance: - return -1 - if i.distance > j.distance: - return 1 - return 0 - if sortNonBinaryNodes: - subTreeList.sort(cmp) - subTree1 = subTreeList[0] - if len(subTreeList) > 1: - for subTree2 in subTreeList[1:]: - subTree1 = BinaryTree(0.0, True, subTree1, subTree2, None) - subTree1.iD = fn2(newickTree, i) - subTree1.distance += fn(newickTree, i) - elif reportUnaryNodes: - subTree1 = BinaryTree(0.0, True, subTree1, None, None) - subTree1.iD = fn2(newickTree, i) - subTree1.distance += fn(newickTree, i) - else: - fn2(newickTree, i) - subTree1.distance += fn(newickTree, i) - return subTree1 - leafID = fn2(newickTree, i) - return BinaryTree(fn(newickTree, i), False, None, None, leafID) - return fn3(newickTree, [0]) - -def printBinaryTree(binaryTree, includeDistances, dontStopAtID=True, distancePrintFn=(lambda f : "%f" % f)): - def fn(binaryTree): - #print " tree Node ", binaryTree.left, binaryTree.right, binaryTree.distance, binaryTree.internal, binaryTree.iD - if binaryTree.iD is not None: - iD = str(binaryTree.iD) - else: - iD = '' - if binaryTree.internal and (dontStopAtID or binaryTree.iD is None): - if binaryTree.right is not None: - s = '(' + fn(binaryTree.left) + ',' + fn(binaryTree.right) + ')' + iD - else: - s = '(' + fn(binaryTree.left) + ')' + iD - else: - s = iD - if includeDistances: - return s + ':' + distancePrintFn(binaryTree.distance) - return s - return fn(binaryTree) + ';' - -######################################################### -######################################################### -######################################################### -#functions for postion weight matrices -######################################################### -######################################################### -######################################################### - -def pWMRead(fileHandle, alphabetSize=4): - """reads in standard position weight matrix format, - rows are different types of base, columns are individual residues - """ - lines = fileHandle.readlines() - assert len(lines) == alphabetSize - l = [ [ float(i) ] for i in lines[0].split() ] - for line in lines[1:]: - l2 = [ float(i) for i in line.split() ] - assert len(l) == len(l2) - for i in xrange(0, len(l)): - l[i].append(l2[i]) - for i in xrange(0, len(l)): - j = sum(l[i]) + 0.0 - l[i] = [ k/j for k in l[i] ] - return l - -def pWMWrite(fileHandle, pWM, alphabetSize=4): - """Writes file in standard PWM format, is reverse of pWMParser - """ - for i in xrange(0, alphabetSize): - fileHandle.write("%s\n" % ' '.join([ str(pWM[j][i]) for j in xrange(0, len(pWM)) ])) - -######################################################### -######################################################### -######################################################### -#Cigar/UCSC Chain functions -######################################################### -######################################################### -######################################################### - -def _checkSegment(start, end, strand): - assert start >= 0 - assert end >= 0 - if strand: - assert start <= end - else: - assert end <= start - assert strand == True or strand == False - -class AlignmentOperation: - def __init__(self, opType, length, score): - self.type = opType - self.length = length - self.score = score - - def __eq__(self, op): - if op is None: - return False - return self.type == op.type and self.length == op.length and close(self.score, op.score, 0.0001) - - def __str__(self): - return "Type: %i Length: %i Score: %f" % (self.type, self.length, self.score) - -class PairwiseAlignment: - #A match in both sequences - PAIRWISE_MATCH = 0 - #A deletion in the query sequence (seq 1) - PAIRWISE_INDEL_Y = 1 - #An insertion in the query sequence (seq 1) - PAIRWISE_INDEL_X = 2 - PAIRWISE_PLUS = '+' - PAIRWISE_MINUS = '-' - - def __init__(self, contig1, start1, end1, strand1, - contig2, start2, end2, strand2, - score, operationList): - _checkSegment(start1, end1, strand1) - _checkSegment(start2, end2, strand2) - - self.contig1 = contig1 - self.start1 = start1 - self.end1 = end1 - self.strand1 = strand1 - self.contig2 = contig2 - self.start2 = start2 - self.end2 = end2 - self.strand2 = strand2 - self.score = score - self.operationList = operationList - - i = sum([ oP.length for oP in operationList if oP.type != PairwiseAlignment.PAIRWISE_INDEL_Y ]) - assert i == abs(end1 - start1) #Check alignment is of right length with respect to the query - - i = sum([ oP.length for oP in operationList if oP.type != PairwiseAlignment.PAIRWISE_INDEL_X ]) - assert i == abs(end2 - start2) #Check alignment is of right length with respect to the target - - def sameCoordinates(self, pairwiseAlignment): - return self.contig1 == pairwiseAlignment.contig1 and \ - self.start1 == pairwiseAlignment.start1 and \ - self.end1 == pairwiseAlignment.end1 and \ - self.strand1 == pairwiseAlignment.strand1 and \ - self.contig2 == pairwiseAlignment.contig2 and \ - self.start2 == pairwiseAlignment.start2 and \ - self.end2 == pairwiseAlignment.end2 and \ - self.strand2 == pairwiseAlignment.strand2 and \ - close(self.score, pairwiseAlignment.score, 0.001) - - def __eq__(self, pairwiseAlignment): - if pairwiseAlignment is None: - return False - return self.sameCoordinates(pairwiseAlignment) and self.operationList == pairwiseAlignment.operationList - -def cigarReadFromString(line): - p = re.compile("cigar:\\s+(.+)\\s+([0-9]+)\\s+([0-9]+)\\s+([\\+\\-\\.])\\s+(.+)\\s+([0-9]+)\\s+([0-9]+)\\s+([\\+\\-\\.])\\s+([^\\s]+)(\\s+(.*)\\s*)*") - i = p.match(line) - if i is not None: - m = i.groups() - if len(m) == 11: - l = m[10].split(" ") - ops = [] - if l != ['']: - j = 0 - while j < len(l): - if l[j] == 'M': - ops.append(AlignmentOperation(PairwiseAlignment.PAIRWISE_MATCH, int(l[j+1]), 0.0)) - j += 2 - elif l[j] == 'D': - ops.append(AlignmentOperation(PairwiseAlignment.PAIRWISE_INDEL_X, int(l[j+1]), 0.0)) #a gap in the query - j += 2 - elif l[j] == 'I': - ops.append(AlignmentOperation(PairwiseAlignment.PAIRWISE_INDEL_Y, int(l[j+1]), 0.0)) #a gap in the target - j += 2 - elif l[j] == 'X': - ops.append(AlignmentOperation(PairwiseAlignment.PAIRWISE_MATCH, int(l[j+1]), float(l[j+2]))) - j += 3 - elif l[j] == 'Y': - ops.append(AlignmentOperation(PairwiseAlignment.PAIRWISE_INDEL_X, int(l[j+1]), float(l[j+2]))) #a gap in the query - j += 3 - else: - assert l[j] == 'Z' - ops.append(AlignmentOperation(PairwiseAlignment.PAIRWISE_INDEL_Y, int(l[j+1]), float(l[j+2]))) #a gap in the target - j += 3 - else: - ops = [] - - assert m[3] == '+' or m[3] == '-' - strand1 = m[3] == '+' - - assert m[7] == '+' or m[7] == '-' - strand2 = m[7] == '+' - - start1, end1 = int(m[1]), int(m[2]) - start2, end2 = int(m[5]), int(m[6]) - - return PairwiseAlignment(m[4], start2, end2, strand2, m[0], start1, end1, strand1, float(m[8]), ops) - return None - -def cigarRead(fileHandleOrFile): - """Reads a list of pairwise alignments into a pairwise alignment structure. - - Query and target are reversed! - """ - fileHandle = _getFileHandle(fileHandleOrFile) - #p = re.compile("cigar:\\s+(.+)\\s+([0-9]+)\\s+([0-9]+)\\s+([\\+\\-\\.])\\s+(.+)\\s+([0-9]+)\\s+([0-9]+)\\s+([\\+\\-\\.])\\s+(.+)\\s+(.*)\\s*)*") - p = re.compile("cigar:\\s+(.+)\\s+([0-9]+)\\s+([0-9]+)\\s+([\\+\\-\\.])\\s+(.+)\\s+([0-9]+)\\s+([0-9]+)\\s+([\\+\\-\\.])\\s+([^\\s]+)(\\s+(.*)\\s*)*") - line = fileHandle.readline() - while line != '': - pA = cigarReadFromString(line) - if pA != None: - yield pA - line = fileHandle.readline() - if isinstance(fileHandleOrFile, "".__class__): - fileHandle.close() - -def cigarWrite(fileHandle, pairwiseAlignment, withProbs=True): - """Writes out the pairwiseAlignment to the file stream. - - Query and target are reversed from normal order. - """ - if len(pairwiseAlignment.operationList) == 0: - logger.info("Writing zero length pairwiseAlignment to file!") - - strand1 = "+" - if not pairwiseAlignment.strand1: - strand1 = "-" - - strand2 = "+" - if not pairwiseAlignment.strand2: - strand2 = "-" - - fileHandle.write("cigar: %s %i %i %s %s %i %i %s %f" % (pairwiseAlignment.contig2, pairwiseAlignment.start2, pairwiseAlignment.end2, strand2,\ - pairwiseAlignment.contig1, pairwiseAlignment.start1, pairwiseAlignment.end1, strand1,\ - pairwiseAlignment.score)) - if withProbs == True: - hashMap = { PairwiseAlignment.PAIRWISE_INDEL_Y:'Z',PairwiseAlignment.PAIRWISE_INDEL_X:'Y', PairwiseAlignment.PAIRWISE_MATCH:'X' } - for op in pairwiseAlignment.operationList: - fileHandle.write(' %s %i %f' % (hashMap[op.type], op.length, op.score)) - else: - hashMap = { PairwiseAlignment.PAIRWISE_INDEL_Y:'I',PairwiseAlignment.PAIRWISE_INDEL_X:'D', PairwiseAlignment.PAIRWISE_MATCH:'M' } - for op in pairwiseAlignment.operationList: - fileHandle.write(' %s %i' % (hashMap[op.type], op.length)) - fileHandle.write("\n") - -def _getRandomSegment(): - contig = random.choice([ "one", "two", "three", "four" ]) - start = random.choice(xrange(0, 10000)) - end = start + random.choice(xrange(0, 1000)) - strand = random.choice([ True, False ]) - if not strand: - start, end = end, start - return contig, start, end, strand - -def getRandomOperationList(xLength, yLength, operationMaxLength=100): - assert operationMaxLength >= 1 - operationList = [] - while xLength > 0 or yLength > 0: - opType = random.choice([ PairwiseAlignment.PAIRWISE_INDEL_Y, PairwiseAlignment.PAIRWISE_INDEL_X, PairwiseAlignment.PAIRWISE_MATCH ]) - if operationMaxLength == 1: - length = 1 - else: - length = random.choice(xrange(1, operationMaxLength)) - if opType != PairwiseAlignment.PAIRWISE_INDEL_Y and xLength - length < 0: - continue - if opType != PairwiseAlignment.PAIRWISE_INDEL_X and yLength - length < 0: - continue - if opType != PairwiseAlignment.PAIRWISE_INDEL_Y: - xLength -= length - if opType != PairwiseAlignment.PAIRWISE_INDEL_X: - yLength -= length - operationList.append(AlignmentOperation(opType, length, random.random())) - assert xLength >= 0 and yLength >= 0 - return operationList - -def getRandomPairwiseAlignment(): - """Gets a random pairwiseAlignment. - """ - i, j, k, l = _getRandomSegment() - m, n, o, p = _getRandomSegment() - score = random.choice(xrange(-1000, 1000)) - return PairwiseAlignment(i, j, k, l, m, n, o, p, score, getRandomOperationList(abs(k - j), abs(o - n))) - -######################################################### -######################################################### -######################################################### -#Graph viz functions. -######################################################### -######################################################### -######################################################### - -def addNodeToGraph(nodeName, graphFileHandle, label, width=0.3, height=0.3, shape="circle", colour="black", fontsize=14): - """Adds a node to the graph. - """ - graphFileHandle.write("node[width=%s,height=%s,shape=%s,colour=%s,fontsize=%s];\n" % (width, height, shape, colour, fontsize)) - graphFileHandle.write("%s [label=\"%s\"];\n" % (nodeName, label)) - -def addEdgeToGraph(parentNodeName, childNodeName, graphFileHandle, colour="black", length="10", weight="1", dir="none", label="", style=""): - """Links two nodes in the graph together. - """ - graphFileHandle.write('edge[color=%s,len=%s,weight=%s,dir=%s,label="%s",style=%s];\n' % (colour, length, weight, dir, label, style)) - graphFileHandle.write("%s -- %s;\n" % (parentNodeName, childNodeName)) - -def setupGraphFile(graphFileHandle): - """Sets up the dot file. - """ - graphFileHandle.write("graph G {\n") - graphFileHandle.write("overlap=false\n") - logger.info("Starting to write the graph") - -def finishGraphFile(graphFileHandle): - """Finishes up the dot file. - """ - graphFileHandle.write("}\n") - logger.info("Finished writing the graph") - -def runGraphViz(graphFile, outputFile, command="dot"): - """Runs graphviz. - """ - system("%s -Tpdf %s > %s" % (command, graphFile, outputFile)) - - -def main(): - pass - -def _test(): - import doctest - return doctest.testmod() - -if __name__ == '__main__': - _test() - main() diff --git a/bioioTest.py b/bioioTest.py deleted file mode 100644 index c7404d1..0000000 --- a/bioioTest.py +++ /dev/null @@ -1,301 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt - -import unittest - -import os -import sys -import random -import math - -from bioio import getTempFile -from bioio import getTempDirectory -from bioio import TempFileTree -from bioio import getRandomAlphaNumericString - -from bioio import fastaRead -from bioio import fastaWrite -from bioio import fastqRead -from bioio import fastqWrite -from bioio import getRandomSequence - -from bioio import pWMRead -from bioio import pWMWrite - -from bioio import newickTreeParser -from bioio import printBinaryTree - -from bioio import cigarRead -from bioio import cigarWrite -from bioio import PairwiseAlignment -from bioio import getRandomPairwiseAlignment - -from sonLib.bioio import TestStatus - -from bioio import system -from bioio import logger - -class TestCase(unittest.TestCase): - - def setUp(self): - self.testNo = TestStatus.getTestSetup() - unittest.TestCase.setUp(self) - self.tempDir = getTempDirectory(os.getcwd()) - self.tempFiles = [] - - def tearDown(self): - unittest.TestCase.tearDown(self) - system("rm -rf %s" % self.tempDir) - for tempFile in self.tempFiles: - os.remove(tempFile) - - ######################################################### - ######################################################### - ######################################################### - #temp file functions - ######################################################### - ######################################################### - ######################################################### - - def testTempFileTree(self): - for test in xrange(100): #self.testNo): - levels = random.choice(xrange(1, 4)) - fileNo = random.choice(xrange(1, 6)) - maxTempFiles = int(math.pow(fileNo, levels)) - - print "Got %s levels, %s fileNo and %s maxTempFiles" % (levels, fileNo, maxTempFiles) - - tempFileTreeRootDir = os.path.join(self.tempDir, getRandomAlphaNumericString()) - tempFileTree = TempFileTree(tempFileTreeRootDir, fileNo, levels) - - tempFiles = [] - tempDirs = [] - #Check we can mac number of temp files. - for i in xrange(maxTempFiles): - if random.random() > 0.5: - tempFile = tempFileTree.getTempFile() - assert os.path.isfile(tempFile) - tempFiles.append(tempFile) - else: - tempFile = tempFileTree.getTempDirectory() - assert os.path.isdir(tempFile) - tempDirs.append(tempFile) - - #Check assertion is created - try: - tempFileTree.getTempFile() - assert False - except RuntimeError: - logger.debug("Got expected error message") - - #Now remove a few temp files - while random.random() > 0.1 and len(tempFiles) > 0: - tempFile = tempFiles.pop() - assert os.path.isfile(tempFile) - tempFileTree.destroyTempFile(tempFile) - assert not os.path.isfile(tempFile) - - #Now remove a few temp dirs - while random.random() > 0.1 and len(tempDirs) > 0: - tempDir = tempDirs.pop() - assert os.path.isdir(tempDir) - tempFileTree.destroyTempDir(tempDir) - assert not os.path.isdir(tempDir) - - #Check temp files is okay - set(tempFileTree.listFiles()) == set(tempFiles + tempDirs) - - #Either remove all the temp files or just destroy the whole thing - if random.random() > 0.5: - #Remove all temp files and check thing is empty. - for tempFile in tempFiles: - tempFileTree.destroyTempFile(tempFile) - for tempDir in tempDirs: - tempFileTree.destroyTempDir(tempDir) - os.remove(os.path.join(tempFileTreeRootDir, "lock")) - os.rmdir(tempFileTreeRootDir) - else: - tempFileTree.destroyTempFiles() - assert not os.path.isdir(tempFileTreeRootDir) - - ######################################################### - ######################################################### - ######################################################### - #fasta functions - ######################################################### - ######################################################### - ######################################################### - - def testFastaReadWrite(self): - tempFile = getTempFile() - self.tempFiles.append(tempFile) - for test in xrange(0, self.testNo): - fastaNumber = random.choice(xrange(10)) - l = [ getRandomSequence() for i in xrange(fastaNumber) ] - fileHandle = open(tempFile, 'w') - for name, seq in l: - fastaWrite(fileHandle, name, seq) - fileHandle.close() - fileHandle = open(tempFile, 'r') - l.reverse() - for i in fastaRead(fileHandle): - assert i == l.pop() - name, seq = i - fastaWrite(sys.stdout, name, seq) - fileHandle.close() - - def testFastqReadWrite(self): - tempFile = getTempFile() - self.tempFiles.append(tempFile) - for test in xrange(0, self.testNo): - fastaNumber = random.choice(xrange(10)) - fastqs = [ (name, seq, [ random.randint(33, 126) for i in range(len(seq)) ]) for name, seq in [ getRandomSequence() for i in xrange(fastaNumber) ]] - fH = open(tempFile, 'w') - for name, seq, quals in fastqs: - fastqWrite(fH, name, seq, quals) - fH.close() - fastqs.reverse() - for i in fastqRead(tempFile): - assert i == fastqs.pop() - name, seq, quals = i - fastqWrite(sys.stdout, name, seq, quals) - - def testFastaReadWriteC(self): - """Tests consistency with C version of this function. - """ - tempFile = getTempFile() - self.tempFiles.append(tempFile) - tempFile2 = getTempFile() - self.tempFiles.append(tempFile2) - for test in xrange(0, self.testNo): - fastaNumber = random.choice(xrange(10)) - l = [ getRandomSequence() for i in xrange(fastaNumber) ] - fileHandle = open(tempFile, 'w') - for name, seq in l: - fastaWrite(fileHandle, name, seq) - fileHandle.close() - - command = "sonLib_fastaCTest %s %s" % (tempFile, tempFile2) - - print command - - system(command) - - fileHandle = open(tempFile2, 'r') - l.reverse() - for i in fastaRead(fileHandle): - name, seq = i - assert i == l.pop() - fastaWrite(sys.stdout, name, seq) - fileHandle.close() - - ######################################################### - ######################################################### - ######################################################### - #newick tree functions - ######################################################### - ######################################################### - ######################################################### - - def testNewickTreeParser(self): - if self.testNo > 0: - d = '((human,baboon),chimp);' - e = newickTreeParser(d) - f = printBinaryTree(e, False) - print d, f - assert d == f - - def testNewickTreeParser_UnaryNodes(self): - #tests with unary nodes - for test in xrange(0, self.testNo): - tree = getRandomTreeString() - logger.debug("tree to try\t", tree) - tree2 = newickTreeParser(tree, reportUnaryNodes=True) - tree3 = printBinaryTree(tree2, True) - logger.debug("tree found\t", tree3) - assert tree == tree3 - - ######################################################### - ######################################################### - ######################################################### - #functions for position weight matrices - ######################################################### - ######################################################### - ######################################################### - - def testPWMParser(self): - tempFile = getTempFile() - self.tempFiles.append(tempFile) - for test in xrange(0, self.testNo): - pWM = getRandomPWM() - - fileHandle = open(tempFile, 'w') - pWMWrite(fileHandle, pWM) - fileHandle.close() - - fileHandle = open(tempFile, 'r') - pWM2 = pWMRead(fileHandle) - fileHandle.close() - - for i in xrange(0, len(pWM)): - pWM[i] == pWM2[i] - - ######################################################### - ######################################################### - ######################################################### - #Cigar functions - ######################################################### - ######################################################### - ######################################################### - - def testCigarReadWrite(self): - tempFile = getTempFile() - self.tempFiles.append(tempFile) - for test in xrange(0, self.testNo): - cigarNumber = random.choice(xrange(10)) - l = [ getRandomPairwiseAlignment() for i in xrange(cigarNumber) ] - fileHandle = open(tempFile, 'w') - for cigar in l: - cigarWrite(fileHandle, cigar) - fileHandle.close() - fileHandle = open(tempFile, 'r') - l.reverse() - for cigar in cigarRead(fileHandle): - cigarWrite(sys.stdout, l[-1]) - cigarWrite(sys.stdout, cigar) - assert cigar == l.pop() - assert len(l) == 0 - fileHandle.close() - -def getRandomTreeString(): - def iDFn(): - return random.choice([ "one", "1", "", "he44"]) - def dFn(): - #if random.random() > 0.5: - return ":%.6f" % random.random() - #return '' - def fn3(): - if random.random() > 0.5: - if random.random() > 0.5: - #is unary - return '(' + fn3() + ')' + iDFn() + dFn() - else: - return '(' + fn3() + "," + fn3() + ')' + iDFn() + dFn() - else: - return iDFn() + dFn() - return fn3() + ';' - -def getRandomPWM(length=-1): - if length == -1: - length = 1 + int(random.random()*10) - def fn(): - l = [ random.random()*100 for i in xrange(0, 4) ] - i = sum(l) - return [ j/i for j in l ] - return [ fn() for i in xrange(0, length) ] - -if __name__ == '__main__': - unittest.main() diff --git a/cigarsTest.py b/cigarsTest.py deleted file mode 100644 index 5339fb4..0000000 --- a/cigarsTest.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt - -import unittest - -import os -import sys -import random - -from bioio import getTempFile - -from bioio import cigarRead -from bioio import cigarWrite -from bioio import getRandomPairwiseAlignment -from bioio import system -from sonLib.bioio import TestStatus -from sonLib.bioio import logger - -class TestCase(unittest.TestCase): - - def setUp(self): - self.testNo = TestStatus.getTestSetup() - self.tempFiles = [] - unittest.TestCase.setUp(self) - - def tearDown(self): - for tempFile in self.tempFiles: - os.remove(tempFile) - unittest.TestCase.tearDown(self) - - def testCigarReadWrite(self): - """Tests the C code for reading and writing cigars against the python parser for cigars. - """ - tempFile = getTempFile() - self.tempFiles.append(tempFile) - for test in xrange(0, self.testNo): - pairwiseAlignmentNumber = random.choice(xrange(10)) - l = [ getRandomPairwiseAlignment() for i in xrange(pairwiseAlignmentNumber) ] - fileHandle = open(tempFile, 'w') - - keepProbs = random.random() > 0.5 - if keepProbs == False: - for pA in l: - for op in pA.operationList: - op.score = 0.0 - - for pairwiseAlignment in l: - cigarWrite(fileHandle, pairwiseAlignment, keepProbs) - fileHandle.close() - - #Now call sonLib_cigarsTest and read and write chains - command = "sonLib_cigarTest %s %s" % (tempFile, keepProbs) - #return - system(command) - - #Now check the chain is okay - fileHandle = open(tempFile, 'r') - l.reverse() - - for pairwiseAlignment in cigarRead(fileHandle): - pairwiseAlignment2 = l.pop() - cigarWrite(sys.stdout, pairwiseAlignment, keepProbs) - cigarWrite(sys.stdout, pairwiseAlignment2, keepProbs) - assert pairwiseAlignment == pairwiseAlignment2 - assert len(l) == 0 - fileHandle.close() - -if __name__ == '__main__': - unittest.main() diff --git a/doc/INSTALL.txt b/doc/INSTALL.txt deleted file mode 100644 index 25db6f1..0000000 --- a/doc/INSTALL.txt +++ /dev/null @@ -1,12 +0,0 @@ -Installing sonLib. - -(1) Place the directory containing sonLib on your python path. i.e. -PYTHONPATH=${PYTHONPATH}:FOO -where FOO/sonLib is the path to the base directory of sonLib. - -(2) Compile the C code: -In sonLib type 'make all' then 'make test' to test the installation - -Linking the C libraries: all libraries built are placed in 'sonLib/lib' - -See https://github.com/benedictpaten/ for different projects. \ No newline at end of file diff --git a/doc/README b/doc/README deleted file mode 100644 index a5b6c99..0000000 --- a/doc/README +++ /dev/null @@ -1,89 +0,0 @@ -This is the readme for 'sonLib', a (very) compact C/Python library for sequence analysis in bioinformatics. - -For basic data-structures it simply contains: - -array lists (automatically resizing) -hash -sorted sets (backed by an AVL tree, currently) -containers (for putting primitives into the above datastructures) -better string functions - -For bioinformatic data-structures it contains for (or will contain): - -Fasta I/O functions -MAF I/O functions -Newick tree I/O functions - -C: - -Usage: - -The header files are in src/sonLib/inc/*.h The global include "sonLib.h", will -include all the public functions in sonLib. - -Naming conventions: - -All functions/objects start with the prefix 'st', this minimises the chances of collisions with -functions in other libraries. - -We use a specific variant for camel case for compound words, i.e. the first letter of every word is capitalised, -except for the first letter of the first word, which is lower case unless it is the name -of an object. - -Acronyms are treated like single words, i.e. we do not capitalise each letter after the first one, e.g. Maf not MAF - -The 'abbreviations' file is a list of agreed on abbreviations. Words should not be abbreviated unless there agreed on -abbreviation is in this file. Most abbreviations should be three letters long. - -All object names are of the form stObject, where Object is the capitalised name of the object, e.g. -stHash, stSortedSet, stList etc. - -Most function names are of the form 'stObject_operation', where Object is the -capitalised name of the object and operation is a camel-case string describing the functions operation -on the object. Some basic functions, e.g. st_malloc, do not have an associated object and so are just -st_operation. We encourage operation strings to be simply verbs, or when the function is acting on an attribute of the object, 'verb noun'. -In some cases where there is no ambiguity about the action associated with -the noun we do not mind dropping the verb, e.g. stObject_length as opposed to stObject_getLength. -The following are function name examples from the library: stHash_insert, stHash_getKeys, -stSortedSet_size, stSortedSet_getFirst, stString_print, stString_copy. - -Documentation: - -Each function should have a comment immediately above its declaration explaining its function, e.g. - -/* - * Set the log level. Either ST_LOGGING_OFF, ST_LOGGING_INFO or ST_LOGGING_DEBUG. - * OFF (no logging), info (middle level), debug (copious logging) - */ -void st_setLogLevel(int32_t level); - -The declaration for most functions is in the header file, so document the header file not the actual -implementation of the function. This allows the user to see the documentation and ignore the actual code! -Do not duplicate this effort by the actual function implementation if seperate from the declaration, -this is extra manual work, and can lead to errors. - -Functions not declared in header files should be static to the src file, and should be documented in the src file. - -I encourage you to use javadoc style documentation for functions, but this is not yet a requirment. - -Testing: - -We use CuTest for unit-testing. -All functions declared in a header file to be used by others should have -an associated unit test. These tests are not lambda calculus, we're not proving the functions correctness, -but the tests should address the obvious cases. - -For an example of the tests see sonLibHashTest.c, to see how these functions are integrated into -the CuTests framework see allTests.c. Larger module level tests, or of actual programs should us the pyUnit -framework, and wrap the code. You can see this in modules using sonLib. - - -Build: - -We use c99 standard. .... - - -Python: - -Module is all of the form sonLib/FOO.py - diff --git a/doc/abbreviations.txt b/doc/abbreviations.txt deleted file mode 100644 index e69de29..0000000 diff --git a/externalTools/Makefile b/externalTools/Makefile deleted file mode 100644 index 45333bf..0000000 --- a/externalTools/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -include ../include.mk -.PHONY: all clean cutestM cutestM.clean quicktreeM.clean - -libPath = ../lib - -all : cutestM quicktreeM - -clean : cutestM.clean quicktreeM.clean - -cutestM : - cd cutest && make all - -cutestM.clean : - cd cutest && make clean - -quicktreeM : - cd quicktree_1.1 && make all CC="${cxx}" - -quicktreeM.clean : - cd quicktree_1.1 && make clean diff --git a/externalTools/cutest/AllTests.c b/externalTools/cutest/AllTests.c deleted file mode 100644 index 5c849ef..0000000 --- a/externalTools/cutest/AllTests.c +++ /dev/null @@ -1,25 +0,0 @@ -#include - -#include "CuTest.h" - -CuSuite* CuGetSuite(); -CuSuite* CuStringGetSuite(); - -void RunAllTests(void) -{ - CuString *output = CuStringNew(); - CuSuite* suite = CuSuiteNew(); - - CuSuiteAddSuite(suite, CuGetSuite()); - CuSuiteAddSuite(suite, CuStringGetSuite()); - - CuSuiteRun(suite); - CuSuiteSummary(suite, output); - CuSuiteDetails(suite, output); - printf("%s\n", output->buffer); -} - -int main(void) -{ - RunAllTests(); -} diff --git a/externalTools/cutest/CuTest.c b/externalTools/cutest/CuTest.c deleted file mode 100644 index 09f9a5e..0000000 --- a/externalTools/cutest/CuTest.c +++ /dev/null @@ -1,342 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "CuTest.h" - -/*-------------------------------------------------------------------------* - * CuStr - *-------------------------------------------------------------------------*/ - -char* CuStrAlloc(int size) -{ - char* newStr = (char*) malloc( sizeof(char) * (size) ); - return newStr; -} - -char* CuStrCopy(const char* old) -{ - int len = strlen(old); - char* newStr = CuStrAlloc(len + 1); - strcpy(newStr, old); - return newStr; -} - -/*-------------------------------------------------------------------------* - * CuString - *-------------------------------------------------------------------------*/ - -void CuStringInit(CuString* str) -{ - str->length = 0; - str->size = STRING_MAX; - str->buffer = (char*) malloc(sizeof(char) * str->size); - str->buffer[0] = '\0'; -} - -CuString* CuStringNew(void) -{ - CuString* str = (CuString*) malloc(sizeof(CuString)); - str->length = 0; - str->size = STRING_MAX; - str->buffer = (char*) malloc(sizeof(char) * str->size); - str->buffer[0] = '\0'; - return str; -} - -void CuStringDelete(CuString *str) -{ - if (!str) return; - free(str->buffer); - free(str); -} - -void CuStringResize(CuString* str, int newSize) -{ - str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); - str->size = newSize; -} - -void CuStringAppend(CuString* str, const char* text) -{ - int length; - - if (text == NULL) { - text = "NULL"; - } - - length = strlen(text); - if (str->length + length + 1 >= str->size) - CuStringResize(str, str->length + length + 1 + STRING_INC); - str->length += length; - strcat(str->buffer, text); -} - -void CuStringAppendChar(CuString* str, char ch) -{ - char text[2]; - text[0] = ch; - text[1] = '\0'; - CuStringAppend(str, text); -} - -void CuStringAppendFormat(CuString* str, const char* format, ...) -{ - va_list argp; - char buf[HUGE_STRING_LEN]; - va_start(argp, format); - vsprintf(buf, format, argp); - va_end(argp); - CuStringAppend(str, buf); -} - -void CuStringInsert(CuString* str, const char* text, int pos) -{ - int length = strlen(text); - if (pos > str->length) - pos = str->length; - if (str->length + length + 1 >= str->size) - CuStringResize(str, str->length + length + 1 + STRING_INC); - memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); - str->length += length; - memcpy(str->buffer + pos, text, length); -} - -/*-------------------------------------------------------------------------* - * CuTest - *-------------------------------------------------------------------------*/ - -void CuTestInit(CuTest* t, const char* name, TestFunction function) -{ - t->name = CuStrCopy(name); - t->failed = 0; - t->ran = 0; - t->message = NULL; - t->function = function; - t->jumpBuf = NULL; -} - -CuTest* CuTestNew(const char* name, TestFunction function) -{ - CuTest* tc = CU_ALLOC(CuTest); - CuTestInit(tc, name, function); - return tc; -} - -void CuTestDelete(CuTest *t) -{ - if (!t) return; - free(t->name); - free(t); -} - -void CuTestRun(CuTest* tc) -{ - jmp_buf buf; - tc->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - tc->ran = 1; - (tc->function)(tc); - } - tc->jumpBuf = 0; -} - -static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) -{ - char buf[HUGE_STRING_LEN]; - - sprintf(buf, "%s:%d: ", file, line); - CuStringInsert(string, buf, 0); - - tc->failed = 1; - tc->message = string->buffer; - if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); -} - -void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) -{ - CuString string; - - CuStringInit(&string); - if (message2 != NULL) - { - CuStringAppend(&string, message2); - CuStringAppend(&string, ": "); - } - CuStringAppend(&string, message); - CuFailInternal(tc, file, line, &string); -} - -void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) -{ - if (condition) return; - CuFail_Line(tc, file, line, NULL, message); -} - -void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, - const char* expected, const char* actual) -{ - CuString string; - if ((expected == NULL && actual == NULL) || - (expected != NULL && actual != NULL && - strcmp(expected, actual) == 0)) - { - return; - } - - CuStringInit(&string); - if (message != NULL) - { - CuStringAppend(&string, message); - CuStringAppend(&string, ": "); - } - CuStringAppend(&string, "expected <"); - CuStringAppend(&string, expected); - CuStringAppend(&string, "> but was <"); - CuStringAppend(&string, actual); - CuStringAppend(&string, ">"); - CuFailInternal(tc, file, line, &string); -} - -void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, - int expected, int actual) -{ - char buf[STRING_MAX]; - if (expected == actual) return; - sprintf(buf, "expected <%d> but was <%d>", expected, actual); - CuFail_Line(tc, file, line, message, buf); -} - -void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, - double expected, double actual, double delta) -{ - char buf[STRING_MAX]; - if (fabs(expected - actual) <= delta) return; - sprintf(buf, "expected <%f> but was <%f>", expected, actual); - - CuFail_Line(tc, file, line, message, buf); -} - -void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, - void* expected, void* actual) -{ - char buf[STRING_MAX]; - if (expected == actual) return; - sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); - CuFail_Line(tc, file, line, message, buf); -} - - -/*-------------------------------------------------------------------------* - * CuSuite - *-------------------------------------------------------------------------*/ - -void CuSuiteInit(CuSuite* testSuite) -{ - testSuite->count = 0; - testSuite->failCount = 0; - memset(testSuite->list, 0, sizeof(testSuite->list)); -} - -CuSuite* CuSuiteNew(void) -{ - CuSuite* testSuite = CU_ALLOC(CuSuite); - CuSuiteInit(testSuite); - return testSuite; -} - -void CuSuiteDelete(CuSuite *testSuite) -{ - unsigned int n; - for (n=0; n < MAX_TEST_CASES; n++) - { - if (testSuite->list[n]) - { - CuTestDelete(testSuite->list[n]); - } - } - free(testSuite); - -} - -void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) -{ - assert(testSuite->count < MAX_TEST_CASES); - testSuite->list[testSuite->count] = testCase; - testSuite->count++; -} - -void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) -{ - int i; - for (i = 0 ; i < testSuite2->count ; ++i) - { - CuTest* testCase = testSuite2->list[i]; - CuSuiteAdd(testSuite, testCase); - testSuite2->list[i] = NULL; - } - CuSuiteDelete(testSuite2); -} - -void CuSuiteRun(CuSuite* testSuite) -{ - int i; - for (i = 0 ; i < testSuite->count ; ++i) - { - CuTest* testCase = testSuite->list[i]; - printf("Running test case %s\n", testCase->name); - CuTestRun(testCase); - if (testCase->failed) { testSuite->failCount += 1; } - } -} - -void CuSuiteSummary(CuSuite* testSuite, CuString* summary) -{ - int i; - for (i = 0 ; i < testSuite->count ; ++i) - { - CuTest* testCase = testSuite->list[i]; - CuStringAppend(summary, testCase->failed ? "F" : "."); - } - CuStringAppend(summary, "\n\n"); -} - -void CuSuiteDetails(CuSuite* testSuite, CuString* details) -{ - int i; - int failCount = 0; - - if (testSuite->failCount == 0) - { - int passCount = testSuite->count - testSuite->failCount; - const char* testWord = passCount == 1 ? "test" : "tests"; - CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); - } - else - { - if (testSuite->failCount == 1) - CuStringAppend(details, "There was 1 failure:\n"); - else - CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); - - for (i = 0 ; i < testSuite->count ; ++i) - { - CuTest* testCase = testSuite->list[i]; - if (testCase->failed) - { - failCount++; - CuStringAppendFormat(details, "%d) %s: %s\n", - failCount, testCase->name, testCase->message); - } - } - CuStringAppend(details, "\n!!!FAILURES!!!\n"); - - CuStringAppendFormat(details, "Runs: %d ", testSuite->count); - CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); - CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); - } -} diff --git a/externalTools/cutest/CuTest.h b/externalTools/cutest/CuTest.h deleted file mode 100644 index 8b32773..0000000 --- a/externalTools/cutest/CuTest.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef CU_TEST_H -#define CU_TEST_H - -#include -#include - -#define CUTEST_VERSION "CuTest 1.5" - -/* CuString */ - -char* CuStrAlloc(int size); -char* CuStrCopy(const char* old); - -#define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE))) - -#define HUGE_STRING_LEN 8192 -#define STRING_MAX 256 -#define STRING_INC 256 - -typedef struct -{ - int length; - int size; - char* buffer; -} CuString; - -void CuStringInit(CuString* str); -CuString* CuStringNew(void); -void CuStringRead(CuString* str, const char* path); -void CuStringAppend(CuString* str, const char* text); -void CuStringAppendChar(CuString* str, char ch); -void CuStringAppendFormat(CuString* str, const char* format, ...); -void CuStringInsert(CuString* str, const char* text, int pos); -void CuStringResize(CuString* str, int newSize); -void CuStringDelete(CuString* str); - -/* CuTest */ - -typedef struct CuTest CuTest; - -typedef void (*TestFunction)(CuTest *); - -struct CuTest -{ - char* name; - TestFunction function; - int failed; - int ran; - const char* message; - jmp_buf *jumpBuf; -}; - -void CuTestInit(CuTest* t, const char* name, TestFunction function); -CuTest* CuTestNew(const char* name, TestFunction function); -void CuTestRun(CuTest* tc); -void CuTestDelete(CuTest *t); - -/* Internal versions of assert functions -- use the public versions */ -void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); -void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); -void CuAssertStrEquals_LineMsg(CuTest* tc, - const char* file, int line, const char* message, - const char* expected, const char* actual); -void CuAssertIntEquals_LineMsg(CuTest* tc, - const char* file, int line, const char* message, - int expected, int actual); -void CuAssertDblEquals_LineMsg(CuTest* tc, - const char* file, int line, const char* message, - double expected, double actual, double delta); -void CuAssertPtrEquals_LineMsg(CuTest* tc, - const char* file, int line, const char* message, - void* expected, void* actual); - -/* public assert functions */ - -#define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms)) -#define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) -#define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) - -#define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) -#define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) -#define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) -#define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) -#define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) -#define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl)) -#define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) -#define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) - -#define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL)) -#define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL)) - -/* CuSuite */ - -#define MAX_TEST_CASES 1024 - -#define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) - -typedef struct -{ - int count; - CuTest* list[MAX_TEST_CASES]; - int failCount; - -} CuSuite; - - -void CuSuiteInit(CuSuite* testSuite); -CuSuite* CuSuiteNew(void); -void CuSuiteDelete(CuSuite *testSuite); -void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase); -void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); -void CuSuiteRun(CuSuite* testSuite); -void CuSuiteSummary(CuSuite* testSuite, CuString* summary); -void CuSuiteDetails(CuSuite* testSuite, CuString* details); - -#endif /* CU_TEST_H */ diff --git a/externalTools/cutest/CuTestTest.c b/externalTools/cutest/CuTestTest.c deleted file mode 100644 index 547f119..0000000 --- a/externalTools/cutest/CuTestTest.c +++ /dev/null @@ -1,709 +0,0 @@ -#include -#include -#include -#include -#include - -#include "CuTest.h" - -/*-------------------------------------------------------------------------* - * Helper functions - *-------------------------------------------------------------------------*/ - -#define CompareAsserts(tc, message, expected, actual) X_CompareAsserts((tc), __FILE__, __LINE__, (message), (expected), (actual)) - -static void X_CompareAsserts(CuTest* tc, const char *file, int line, const char* message, const char* expected, const char* actual) -{ - int mismatch; - if (expected == NULL || actual == NULL) { - mismatch = (expected != NULL || actual != NULL); - } else { - const char *front = __FILE__ ":"; - const size_t frontLen = strlen(front); - const size_t expectedLen = strlen(expected); - - const char *matchStr = actual; - - mismatch = (strncmp(matchStr, front, frontLen) != 0); - if (!mismatch) { - matchStr = strchr(matchStr + frontLen, ':'); - mismatch |= (matchStr == NULL || strncmp(matchStr, ": ", 2)); - if (!mismatch) { - matchStr += 2; - mismatch |= (strncmp(matchStr, expected, expectedLen) != 0); - } - } - } - - CuAssert_Line(tc, file, line, message, !mismatch); -} - -/*-------------------------------------------------------------------------* - * CuString Test - *-------------------------------------------------------------------------*/ - -void TestCuStringNew(CuTest* tc) -{ - CuString* str = CuStringNew(); - CuAssertTrue(tc, 0 == str->length); - CuAssertTrue(tc, 0 != str->size); - CuAssertStrEquals(tc, "", str->buffer); -} - - -void TestCuStringAppend(CuTest* tc) -{ - CuString* str = CuStringNew(); - CuStringAppend(str, "hello"); - CuAssertIntEquals(tc, 5, str->length); - CuAssertStrEquals(tc, "hello", str->buffer); - CuStringAppend(str, " world"); - CuAssertIntEquals(tc, 11, str->length); - CuAssertStrEquals(tc, "hello world", str->buffer); -} - - -void TestCuStringAppendNULL(CuTest* tc) -{ - CuString* str = CuStringNew(); - CuStringAppend(str, NULL); - CuAssertIntEquals(tc, 4, str->length); - CuAssertStrEquals(tc, "NULL", str->buffer); -} - - -void TestCuStringAppendChar(CuTest* tc) -{ - CuString* str = CuStringNew(); - CuStringAppendChar(str, 'a'); - CuStringAppendChar(str, 'b'); - CuStringAppendChar(str, 'c'); - CuStringAppendChar(str, 'd'); - CuAssertIntEquals(tc, 4, str->length); - CuAssertStrEquals(tc, "abcd", str->buffer); -} - - -void TestCuStringInserts(CuTest* tc) -{ - CuString* str = CuStringNew(); - CuStringAppend(str, "world"); - CuAssertIntEquals(tc, 5, str->length); - CuAssertStrEquals(tc, "world", str->buffer); - CuStringInsert(str, "hell", 0); - CuAssertIntEquals(tc, 9, str->length); - CuAssertStrEquals(tc, "hellworld", str->buffer); - CuStringInsert(str, "o ", 4); - CuAssertIntEquals(tc, 11, str->length); - CuAssertStrEquals(tc, "hello world", str->buffer); - CuStringInsert(str, "!", 11); - CuAssertIntEquals(tc, 12, str->length); - CuAssertStrEquals(tc, "hello world!", str->buffer); -} - - -void TestCuStringResizes(CuTest* tc) -{ - CuString* str = CuStringNew(); - int i; - for(i = 0 ; i < STRING_MAX ; ++i) - { - CuStringAppend(str, "aa"); - } - CuAssertTrue(tc, STRING_MAX * 2 == str->length); - CuAssertTrue(tc, STRING_MAX * 2 <= str->size); -} - -CuSuite* CuStringGetSuite(void) -{ - CuSuite* suite = CuSuiteNew(); - - SUITE_ADD_TEST(suite, TestCuStringNew); - SUITE_ADD_TEST(suite, TestCuStringAppend); - SUITE_ADD_TEST(suite, TestCuStringAppendNULL); - SUITE_ADD_TEST(suite, TestCuStringAppendChar); - SUITE_ADD_TEST(suite, TestCuStringInserts); - SUITE_ADD_TEST(suite, TestCuStringResizes); - - return suite; -} - -/*-------------------------------------------------------------------------* - * CuTest Test - *-------------------------------------------------------------------------*/ - -void TestPasses(CuTest* tc) -{ - CuAssert(tc, "test should pass", 1 == 0 + 1); -} - -void zTestFails(CuTest* tc) -{ - CuAssert(tc, "test should fail", 1 == 1 + 1); -} - - -void TestCuTestNew(CuTest* tc) -{ - CuTest* tc2 = CuTestNew("MyTest", TestPasses); - CuAssertStrEquals(tc, "MyTest", tc2->name); - CuAssertTrue(tc, !tc2->failed); - CuAssertTrue(tc, tc2->message == NULL); - CuAssertTrue(tc, tc2->function == TestPasses); - CuAssertTrue(tc, tc2->ran == 0); - CuAssertTrue(tc, tc2->jumpBuf == NULL); -} - - -void TestCuTestInit(CuTest *tc) -{ - CuTest tc2; - CuTestInit(&tc2, "MyTest", TestPasses); - CuAssertStrEquals(tc, "MyTest", tc2.name); - CuAssertTrue(tc, !tc2.failed); - CuAssertTrue(tc, tc2.message == NULL); - CuAssertTrue(tc, tc2.function == TestPasses); - CuAssertTrue(tc, tc2.ran == 0); - CuAssertTrue(tc, tc2.jumpBuf == NULL); -} - -void TestCuAssert(CuTest* tc) -{ - CuTest tc2; - CuTestInit(&tc2, "MyTest", TestPasses); - - CuAssert(&tc2, "test 1", 5 == 4 + 1); - CuAssertTrue(tc, !tc2.failed); - CuAssertTrue(tc, tc2.message == NULL); - - CuAssert(&tc2, "test 2", 0); - CuAssertTrue(tc, tc2.failed); - CompareAsserts(tc, "CuAssert didn't fail", "test 2", tc2.message); - - CuAssert(&tc2, "test 3", 1); - CuAssertTrue(tc, tc2.failed); - CompareAsserts(tc, "CuAssert didn't fail", "test 2", tc2.message); - - CuAssert(&tc2, "test 4", 0); - CuAssertTrue(tc, tc2.failed); - CompareAsserts(tc, "CuAssert didn't fail", "test 4", tc2.message); - -} - -void TestCuAssertPtrEquals_Success(CuTest* tc) -{ - CuTest tc2; - int x; - - CuTestInit(&tc2, "MyTest", TestPasses); - - /* test success case */ - CuAssertPtrEquals(&tc2, &x, &x); - CuAssertTrue(tc, ! tc2.failed); - CuAssertTrue(tc, NULL == tc2.message); -} - -void TestCuAssertPtrEquals_Failure(CuTest* tc) -{ - CuTest tc2; - int x; - int* nullPtr = NULL; - char expected_message[STRING_MAX]; - - CuTestInit(&tc2, "MyTest", TestPasses); - - /* test failing case */ - sprintf(expected_message, "expected pointer <0x%p> but was <0x%p>", nullPtr, &x); - CuAssertPtrEquals(&tc2, NULL, &x); - CuAssertTrue(tc, tc2.failed); - CompareAsserts(tc, "CuAssertPtrEquals failed", expected_message, tc2.message); -} - -void TestCuAssertPtrNotNull_Success(CuTest* tc) -{ - CuTest tc2; - int x; - - CuTestInit(&tc2, "MyTest", TestPasses); - - /* test success case */ - CuAssertPtrNotNull(&tc2, &x); - CuAssertTrue(tc, ! tc2.failed); - CuAssertTrue(tc, NULL == tc2.message); -} - -void TestCuAssertPtrNotNull_Failure(CuTest* tc) -{ - CuTest tc2; - - CuTestInit(&tc2, "MyTest", TestPasses); - - /* test failing case */ - CuAssertPtrNotNull(&tc2, NULL); - CuAssertTrue(tc, tc2.failed); - CompareAsserts(tc, "CuAssertPtrNotNull failed", "null pointer unexpected", tc2.message); -} - -void TestCuTestRun(CuTest* tc) -{ - CuTest tc2; - CuTestInit(&tc2, "MyTest", zTestFails); - CuTestRun(&tc2); - - CuAssertStrEquals(tc, "MyTest", tc2.name); - CuAssertTrue(tc, tc2.failed); - CuAssertTrue(tc, tc2.ran); - CompareAsserts(tc, "TestRun failed", "test should fail", tc2.message); -} - -/*-------------------------------------------------------------------------* - * CuSuite Test - *-------------------------------------------------------------------------*/ - -void TestCuSuiteInit(CuTest* tc) -{ - CuSuite ts; - CuSuiteInit(&ts); - CuAssertTrue(tc, ts.count == 0); - CuAssertTrue(tc, ts.failCount == 0); -} - -void TestCuSuiteNew(CuTest* tc) -{ - CuSuite* ts = CuSuiteNew(); - CuAssertTrue(tc, ts->count == 0); - CuAssertTrue(tc, ts->failCount == 0); -} - -void TestCuSuiteAddTest(CuTest* tc) -{ - CuSuite ts; - CuTest tc2; - - CuSuiteInit(&ts); - CuTestInit(&tc2, "MyTest", zTestFails); - - CuSuiteAdd(&ts, &tc2); - CuAssertTrue(tc, ts.count == 1); - - CuAssertStrEquals(tc, "MyTest", ts.list[0]->name); -} - -void TestCuSuiteAddSuite(CuTest* tc) -{ - CuSuite* ts1 = CuSuiteNew(); - CuSuite* ts2 = CuSuiteNew(); - - CuSuiteAdd(ts1, CuTestNew("TestFails1", zTestFails)); - CuSuiteAdd(ts1, CuTestNew("TestFails2", zTestFails)); - - CuSuiteAdd(ts2, CuTestNew("TestFails3", zTestFails)); - CuSuiteAdd(ts2, CuTestNew("TestFails4", zTestFails)); - - CuSuiteAddSuite(ts1, ts2); - CuAssertIntEquals(tc, 4, ts1->count); - - CuAssertStrEquals(tc, "TestFails1", ts1->list[0]->name); - CuAssertStrEquals(tc, "TestFails2", ts1->list[1]->name); - CuAssertStrEquals(tc, "TestFails3", ts1->list[2]->name); - CuAssertStrEquals(tc, "TestFails4", ts1->list[3]->name); -} - -void TestCuSuiteRun(CuTest* tc) -{ - CuSuite ts; - CuTest tc1, tc2, tc3, tc4; - - CuSuiteInit(&ts); - CuTestInit(&tc1, "TestPasses", TestPasses); - CuTestInit(&tc2, "TestPasses", TestPasses); - CuTestInit(&tc3, "TestFails", zTestFails); - CuTestInit(&tc4, "TestFails", zTestFails); - - CuSuiteAdd(&ts, &tc1); - CuSuiteAdd(&ts, &tc2); - CuSuiteAdd(&ts, &tc3); - CuSuiteAdd(&ts, &tc4); - CuAssertTrue(tc, ts.count == 4); - - CuSuiteRun(&ts); - CuAssertTrue(tc, ts.count - ts.failCount == 2); - CuAssertTrue(tc, ts.failCount == 2); -} - -void TestCuSuiteSummary(CuTest* tc) -{ - CuSuite ts; - CuTest tc1, tc2; - CuString summary; - - CuSuiteInit(&ts); - CuTestInit(&tc1, "TestPasses", TestPasses); - CuTestInit(&tc2, "TestFails", zTestFails); - CuStringInit(&summary); - - CuSuiteAdd(&ts, &tc1); - CuSuiteAdd(&ts, &tc2); - CuSuiteRun(&ts); - - CuSuiteSummary(&ts, &summary); - - CuAssertTrue(tc, ts.count == 2); - CuAssertTrue(tc, ts.failCount == 1); - CuAssertStrEquals(tc, ".F\n\n", summary.buffer); -} - - -void TestCuSuiteDetails_SingleFail(CuTest* tc) -{ - CuSuite ts; - CuTest tc1, tc2; - CuString details; - const char* front; - const char* back; - - CuSuiteInit(&ts); - CuTestInit(&tc1, "TestPasses", TestPasses); - CuTestInit(&tc2, "TestFails", zTestFails); - CuStringInit(&details); - - CuSuiteAdd(&ts, &tc1); - CuSuiteAdd(&ts, &tc2); - CuSuiteRun(&ts); - - CuSuiteDetails(&ts, &details); - - CuAssertTrue(tc, ts.count == 2); - CuAssertTrue(tc, ts.failCount == 1); - - front = "There was 1 failure:\n" - "1) TestFails: "; - back = "test should fail\n" - "\n!!!FAILURES!!!\n" - "Runs: 2 Passes: 1 Fails: 1\n"; - - CuAssertStrEquals(tc, back, details.buffer + strlen(details.buffer) - strlen(back)); - details.buffer[strlen(front)] = 0; - CuAssertStrEquals(tc, front, details.buffer); -} - - -void TestCuSuiteDetails_SinglePass(CuTest* tc) -{ - CuSuite ts; - CuTest tc1; - CuString details; - const char* expected; - - CuSuiteInit(&ts); - CuTestInit(&tc1, "TestPasses", TestPasses); - CuStringInit(&details); - - CuSuiteAdd(&ts, &tc1); - CuSuiteRun(&ts); - - CuSuiteDetails(&ts, &details); - - CuAssertTrue(tc, ts.count == 1); - CuAssertTrue(tc, ts.failCount == 0); - - expected = - "OK (1 test)\n"; - - CuAssertStrEquals(tc, expected, details.buffer); -} - -void TestCuSuiteDetails_MultiplePasses(CuTest* tc) -{ - CuSuite ts; - CuTest tc1, tc2; - CuString details; - const char* expected; - - CuSuiteInit(&ts); - CuTestInit(&tc1, "TestPasses", TestPasses); - CuTestInit(&tc2, "TestPasses", TestPasses); - CuStringInit(&details); - - CuSuiteAdd(&ts, &tc1); - CuSuiteAdd(&ts, &tc2); - CuSuiteRun(&ts); - - CuSuiteDetails(&ts, &details); - - CuAssertTrue(tc, ts.count == 2); - CuAssertTrue(tc, ts.failCount == 0); - - expected = - "OK (2 tests)\n"; - - CuAssertStrEquals(tc, expected, details.buffer); -} - -void TestCuSuiteDetails_MultipleFails(CuTest* tc) -{ - CuSuite ts; - CuTest tc1, tc2; - CuString details; - const char* front; - const char* mid; - const char* back; - - CuSuiteInit(&ts); - CuTestInit(&tc1, "TestFails1", zTestFails); - CuTestInit(&tc2, "TestFails2", zTestFails); - CuStringInit(&details); - - CuSuiteAdd(&ts, &tc1); - CuSuiteAdd(&ts, &tc2); - CuSuiteRun(&ts); - - CuSuiteDetails(&ts, &details); - - CuAssertTrue(tc, ts.count == 2); - CuAssertTrue(tc, ts.failCount == 2); - - front = - "There were 2 failures:\n" - "1) TestFails1: "; - mid = "test should fail\n" - "2) TestFails2: "; - back = "test should fail\n" - "\n!!!FAILURES!!!\n" - "Runs: 2 Passes: 0 Fails: 2\n"; - - CuAssertStrEquals(tc, back, details.buffer + strlen(details.buffer) - strlen(back)); - CuAssert(tc, "Couldn't find middle", strstr(details.buffer, mid) != NULL); - details.buffer[strlen(front)] = 0; - CuAssertStrEquals(tc, front, details.buffer); -} - - -/*-------------------------------------------------------------------------* - * Misc Test - *-------------------------------------------------------------------------*/ - -void TestCuStrCopy(CuTest* tc) -{ - const char* old = "hello world"; - const char* newStr = CuStrCopy(old); - CuAssert(tc, "old is new", strcmp(old, newStr) == 0); -} - - -void TestCuStringAppendFormat(CuTest* tc) -{ - int i; - char* text = CuStrAlloc(301); /* long string */ - CuString* str = CuStringNew(); - for (i = 0 ; i < 300 ; ++i) - text[i] = 'a'; - text[300] = '\0'; - CuStringAppendFormat(str, "%s", text); - - /* buffer limit raised to HUGE_STRING_LEN so no overflow */ - - CuAssert(tc, "length of str->buffer is 300", 300 == strlen(str->buffer)); -} - -void TestFail(CuTest* tc) -{ - jmp_buf buf; - int pointReached = 0; - CuTest* tc2 = CuTestNew("TestFails", zTestFails); - tc2->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - CuFail(tc2, "hello world"); - pointReached = 1; - } - CuAssert(tc, "point was not reached", pointReached == 0); -} - -void TestAssertStrEquals(CuTest* tc) -{ - jmp_buf buf; - CuTest *tc2 = CuTestNew("TestAssertStrEquals", zTestFails); - - const char* expected = "expected but was "; - const char *expectedMsg = "some text: expected but was "; - - tc2->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - CuAssertStrEquals(tc2, "hello", "world"); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertStrEquals failed", expected, tc2->message); - if (setjmp(buf) == 0) - { - CuAssertStrEquals_Msg(tc2, "some text", "hello", "world"); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertStrEquals failed", expectedMsg, tc2->message); -} - -void TestAssertStrEquals_NULL(CuTest* tc) -{ - jmp_buf buf; - CuTest *tc2 = CuTestNew("TestAssertStrEquals_NULL", zTestFails); - - tc2->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - CuAssertStrEquals(tc2, NULL, NULL); - } - CuAssertTrue(tc, !tc2->failed); - CompareAsserts(tc, "CuAssertStrEquals_NULL failed", NULL, tc2->message); - if (setjmp(buf) == 0) - { - CuAssertStrEquals_Msg(tc2, "some text", NULL, NULL); - } - CuAssertTrue(tc, !tc2->failed); - CompareAsserts(tc, "CuAssertStrEquals_NULL failed", NULL, tc2->message); -} - -void TestAssertStrEquals_FailNULLStr(CuTest* tc) -{ - jmp_buf buf; - CuTest *tc2 = CuTestNew("TestAssertStrEquals_FailNULLStr", zTestFails); - - const char* expected = "expected but was "; - const char *expectedMsg = "some text: expected but was "; - - tc2->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - CuAssertStrEquals(tc2, "hello", NULL); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertStrEquals_FailNULLStr failed", expected, tc2->message); - if (setjmp(buf) == 0) - { - CuAssertStrEquals_Msg(tc2, "some text", "hello", NULL); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertStrEquals_FailNULLStr failed", expectedMsg, tc2->message); -} - -void TestAssertStrEquals_FailStrNULL(CuTest* tc) -{ - jmp_buf buf; - CuTest *tc2 = CuTestNew("TestAssertStrEquals_FailStrNULL", zTestFails); - - const char* expected = "expected but was "; - const char *expectedMsg = "some text: expected but was "; - - tc2->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - CuAssertStrEquals(tc2, NULL, "hello"); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertStrEquals_FailStrNULL failed", expected, tc2->message); - if (setjmp(buf) == 0) - { - CuAssertStrEquals_Msg(tc2, "some text", NULL, "hello"); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertStrEquals_FailStrNULL failed", expectedMsg, tc2->message); -} - -void TestAssertIntEquals(CuTest* tc) -{ - jmp_buf buf; - CuTest *tc2 = CuTestNew("TestAssertIntEquals", zTestFails); - const char* expected = "expected <42> but was <32>"; - const char* expectedMsg = "some text: expected <42> but was <32>"; - tc2->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - CuAssertIntEquals(tc2, 42, 32); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertIntEquals failed", expected, tc2->message); - if (setjmp(buf) == 0) - { - CuAssertIntEquals_Msg(tc2, "some text", 42, 32); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertStrEquals failed", expectedMsg, tc2->message); -} - -void TestAssertDblEquals(CuTest* tc) -{ - jmp_buf buf; - double x = 3.33; - double y = 10.0 / 3.0; - CuTest *tc2 = CuTestNew("TestAssertDblEquals", zTestFails); - char expected[STRING_MAX]; - char expectedMsg[STRING_MAX]; - sprintf(expected, "expected <%lf> but was <%lf>", x, y); - sprintf(expectedMsg, "some text: expected <%lf> but was <%lf>", x, y); - - CuTestInit(tc2, "TestAssertDblEquals", TestPasses); - - CuAssertDblEquals(tc2, x, x, 0.0); - CuAssertTrue(tc, ! tc2->failed); - CuAssertTrue(tc, NULL == tc2->message); - - CuAssertDblEquals(tc2, x, y, 0.01); - CuAssertTrue(tc, ! tc2->failed); - CuAssertTrue(tc, NULL == tc2->message); - - tc2->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - CuAssertDblEquals(tc2, x, y, 0.001); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertDblEquals failed", expected, tc2->message); - tc2->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - CuAssertDblEquals_Msg(tc2, "some text", x, y, 0.001); - } - CuAssertTrue(tc, tc2->failed); - CompareAsserts(tc, "CuAssertDblEquals failed", expectedMsg, tc2->message); -} - -/*-------------------------------------------------------------------------* - * main - *-------------------------------------------------------------------------*/ - -CuSuite* CuGetSuite(void) -{ - CuSuite* suite = CuSuiteNew(); - - SUITE_ADD_TEST(suite, TestCuStringAppendFormat); - SUITE_ADD_TEST(suite, TestCuStrCopy); - SUITE_ADD_TEST(suite, TestFail); - SUITE_ADD_TEST(suite, TestAssertStrEquals); - SUITE_ADD_TEST(suite, TestAssertStrEquals_NULL); - SUITE_ADD_TEST(suite, TestAssertStrEquals_FailStrNULL); - SUITE_ADD_TEST(suite, TestAssertStrEquals_FailNULLStr); - SUITE_ADD_TEST(suite, TestAssertIntEquals); - SUITE_ADD_TEST(suite, TestAssertDblEquals); - - SUITE_ADD_TEST(suite, TestCuTestNew); - SUITE_ADD_TEST(suite, TestCuTestInit); - SUITE_ADD_TEST(suite, TestCuAssert); - SUITE_ADD_TEST(suite, TestCuAssertPtrEquals_Success); - SUITE_ADD_TEST(suite, TestCuAssertPtrEquals_Failure); - SUITE_ADD_TEST(suite, TestCuAssertPtrNotNull_Success); - SUITE_ADD_TEST(suite, TestCuAssertPtrNotNull_Failure); - SUITE_ADD_TEST(suite, TestCuTestRun); - - SUITE_ADD_TEST(suite, TestCuSuiteInit); - SUITE_ADD_TEST(suite, TestCuSuiteNew); - SUITE_ADD_TEST(suite, TestCuSuiteAddTest); - SUITE_ADD_TEST(suite, TestCuSuiteAddSuite); - SUITE_ADD_TEST(suite, TestCuSuiteRun); - SUITE_ADD_TEST(suite, TestCuSuiteSummary); - SUITE_ADD_TEST(suite, TestCuSuiteDetails_SingleFail); - SUITE_ADD_TEST(suite, TestCuSuiteDetails_SinglePass); - SUITE_ADD_TEST(suite, TestCuSuiteDetails_MultiplePasses); - SUITE_ADD_TEST(suite, TestCuSuiteDetails_MultipleFails); - - return suite; -} diff --git a/externalTools/cutest/Makefile b/externalTools/cutest/Makefile deleted file mode 100644 index 5f89039..0000000 --- a/externalTools/cutest/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -include ../../include.mk -binPath = ../../bin -libPath = ../../lib - -all : ${libPath}/cuTest.a - -clean : -#Removing test binaries - rm -f ${libPath}/cuTest.a ${libPath}/CuTest.h - -${libPath}/cuTest.a : CuTest.c CuTest.h - @mkdir -p $(dir $@) - ${cxx} $(CPPFLAGS) $(CFLAGS) ${cflags} -c CuTest.c - ar rc cuTest.a *.o - ranlib cuTest.a - rm -f *.o - mv cuTest.a ${libPath}/ - cp CuTest.h ${libPath}/ diff --git a/externalTools/cutest/README.txt b/externalTools/cutest/README.txt deleted file mode 100644 index 12b9796..0000000 --- a/externalTools/cutest/README.txt +++ /dev/null @@ -1,211 +0,0 @@ -HOW TO USE - -You can use CuTest to create unit tests to drive your development -in the style of Extreme Programming. You can also add unit tests to -existing code to ensure that it works as you suspect. - -Your unit tests are an investment. They let you to change your -code and add new features confidently without worrying about -accidentally breaking earlier features. - - -LICENSING - -For details on licensing see license.txt. - - -GETTING STARTED - -To add unit testing to your C code the only files you need are -CuTest.c and CuTest.h. - -CuTestTest.c and AllTests.c have been included to provide an -example of how to write unit tests and then how to aggregate them -into suites and into a single AllTests.c file. Suites allow you -to put group tests into logical sets. AllTests.c combines all the -suites and runs them. - -You should not have to look inside CuTest.c. Looking in -CuTestTest.c and AllTests.c (for example usage) should be -sufficient. - -After downloading the sources, run your compiler to create an -executable called AllTests.exe. For example, if you are using -Windows with the cl.exe compiler you would type: - - cl.exe AllTests.c CuTest.c CuTestTest.c - AllTests.exe - -This will run all the unit tests associated with CuTest and print -the output on the console. You can replace cl.exe with gcc or -your favorite compiler in the command above. - - -DETAILED EXAMPLE - -Here is a more detailed example. We will work through a simple -test first exercise. The goal is to create a library of string -utilities. First, lets write a function that converts a -null-terminated string to all upper case. - -Ensure that CuTest.c and CuTest.h are accessible from your C -project. Next, create a file called StrUtil.c with these -contents: - - #include "CuTest.h" - - char* StrToUpper(char* str) { - return str; - } - - void TestStrToUpper(CuTest *tc) { - char* input = strdup("hello world"); - char* actual = StrToUpper(input); - char* expected = "HELLO WORLD"; - CuAssertStrEquals(tc, expected, actual); - } - - CuSuite* StrUtilGetSuite() { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, TestStrToUpper); - return suite; - } - -Create another file called AllTests.c with these contents: - - #include "CuTest.h" - - CuSuite* StrUtilGetSuite(); - - void RunAllTests(void) { - CuString *output = CuStringNew(); - CuSuite* suite = CuSuiteNew(); - - CuSuiteAddSuite(suite, StrUtilGetSuite()); - - CuSuiteRun(suite); - CuSuiteSummary(suite, output); - CuSuiteDetails(suite, output); - printf("%s\n", output->buffer); - } - - int main(void) { - RunAllTests(); - } - -Then type this on the command line: - - gcc AllTests.c CuTest.c StrUtil.c - -to compile. You can replace gcc with your favorite compiler. -CuTest should be portable enough to handle all Windows and Unix -compilers. Then to run the tests type: - - a.out - -This will print an error because we haven't implemented the -StrToUpper function correctly. We are just returning the string -without changing it to upper case. - - char* StrToUpper(char* str) { - return str; - } - -Rewrite this as follows: - - char* StrToUpper(char* str) { - char* p; - for (p = str ; *p ; ++p) *p = toupper(*p); - return str; - } - -Recompile and run the tests again. The test should pass this -time. - - -WHAT TO DO NEXT - -At this point you might want to write more tests for the -StrToUpper function. Here are some ideas: - -TestStrToUpper_EmptyString : pass in "" -TestStrToUpper_UpperCase : pass in "HELLO WORLD" -TestStrToUpper_MixedCase : pass in "HELLO world" -TestStrToUpper_Numbers : pass in "1234 hello" - -As you write each one of these tests add it to StrUtilGetSuite -function. If you don't the tests won't be run. Later as you write -other functions and write tests for them be sure to include those -in StrUtilGetSuite also. The StrUtilGetSuite function should -include all the tests in StrUtil.c - -Over time you will create another file called FunkyStuff.c -containing other functions unrelated to StrUtil. Follow the same -pattern. Create a FunkyStuffGetSuite function in FunkyStuff.c. -And add FunkyStuffGetSuite to AllTests.c. - -The framework is designed in the way it is so that it is easy to -organize a lot of tests. - -THE BIG PICTURE - -Each individual test corresponds to a CuTest. These are grouped -to form a CuSuite. CuSuites can hold CuTests or other CuSuites. -AllTests.c collects all the CuSuites in the program into a single -CuSuite which it then runs as a single CuSuite. - -The project is open source so feel free to take a peek under the -hood at the CuTest.c file to see how it works. CuTestTest.c -contains tests for CuTest.c. So CuTest tests itself. - -Since AllTests.c has a main() you will need to exclude this when -you are building your product. Here is a nicer way to do this if -you want to avoid messing with multiple builds. Remove the main() -in AllTests.c. Note that it just calls RunAllTests(). Instead -we'll call this directly from the main program. - -Now in the main() of the actual program check to see if the -command line option "--test" was passed. If it was then I call -RunAllTests() from AllTests.c. Otherwise run the real program. - -Shipping the tests with the code can be useful. If you customers -complain about a problem you can ask them to run the unit tests -and send you the output. This can help you to quickly isolate the -piece of your system that is malfunctioning in the customer's -environment. - -CuTest offers a rich set of CuAssert functions. Here is a list: - -void CuAssert(CuTest* tc, char* message, int condition); -void CuAssertTrue(CuTest* tc, int condition); -void CuAssertStrEquals(CuTest* tc, char* expected, char* actual); -void CuAssertIntEquals(CuTest* tc, int expected, int actual); -void CuAssertPtrEquals(CuTest* tc, void* expected, void* actual); -void CuAssertPtrNotNull(CuTest* tc, void* pointer); - -The project is open source and so you can add other more powerful -asserts to make your tests easier to write and more concise. -Please feel free to send me changes you make so that I can -incorporate them into future releases. - -If you see any errors in this document please contact me at -asimjalis@peakprogramming.com. - - -AUTOMATING TEST SUITE GENERATION - -make-tests.sh will grep through all the .c files in the current -directory and generate the code to run all the tests contained in -them. Using this script you don't have to worry about writing -AllTests.c or dealing with any of the other suite code. - - -CREDITS - -These people have contributed useful code changes to the CuTest project. -Thanks! - -- [02.23.2003] Dave Glowacki -- [04.17.2009] Tobias Lippert -- [11.13.2009] Eli Bendersky -- [12.14.2009] Andrew Brown diff --git a/externalTools/cutest/index.html b/externalTools/cutest/index.html deleted file mode 100644 index f8c9a42..0000000 --- a/externalTools/cutest/index.html +++ /dev/null @@ -1,196 +0,0 @@ - - - - - -CuTest: The Cutest C Unit Testing Framework - - - - - - - -
-
-
- -[ - Download Now -| Download Statistics -| Browse Source -| SourceForge -| Blog -| asimjalis(nospam)gmail.com -] - -
- - -

CuTest: C Unit Testing Framework

- - -

Overview

- -CuTest is a unit testing library for the C language. It can be -used to do Extreme Programming and Test-First Development in the -C language. It's a fun and cute library that will make your -programming fun and productive. - -

Benefits

- -
    - -
  • Lower Defects. The tests ensure that your code keeps working -as you make small changes in it. - -
  • Faster Debugging. The tests tell you which subroutine is -broken. You avoid spending hours trying to figure out what's -broken. - -
  • Development Speed. You trust your old code and can keep -adding to it without worrying about bad interactions. If there is -a bad interaction the tests will catch it. - -
  • Permanent Bug Fixes. If every time a bug is reported you -write a quick test, you will guarantee that the bug never -reappears again. - -
  • Fun. As your bug count drops you will begin to enjoy -programming like you've never done before. Running the tests -every few minutes and seeing them pass feels good. - -
- -

Features

- -
    - -
  • Small. Consists of a single .c and .h file. - -
  • Easy to Deploy. Just drop the two files into your source -tree. - -
  • Highly Portable. Works with all major compilers on Windows -(Microsoft, Borland), Linux, Unix, PalmOS. - -
  • Open Source. You can extend it to add more functionality. -The source can be invaluable if you are trying to trace a test -failure. - -
  • Cuteness. Of all the testing frameworks CuTest has the -cutest name :-) - -
- - -

Licensing

- -CuTest is distributed under the zlib/libpng -license. See license.txt in the distribution for text of license. The -intent of the license is to: - -
    - -
  • Keep the license as simple as possible -
  • Encourage the use of CuTest in both free and commercial applications and libraries -
  • Keep the source code together -
  • Give credit to the CuTest contributors for their work - -
- -If you find CuTest useful we would like to hear about it. - - -

Getting Started

- -

For a detailed tutorial see README in the distribution. This shows you how -to organize your tests and how to autogenerate the AllTests.c file from your -source files. - -

To add unit testing to your C code the only files you need -are CuTest.c and CuTest.h. - -

CuTestTest.c and AllTests.c have been included to provide an -example of how to write unit tests and then how to aggregate them -into suites and into a single AllTests.c file. Suites allow you -to put unit tests for different parts of your code in different -files. AllTests.c combines all the suites and runs them. - -

You should not have to look inside CuTest.c. Looking in -CuTestTest.c (for example usage) should be sufficient. - -

After downloading the sources, run your compiler to create an -executable called AllTests.exe. For example, if you are using -Windows you would type: - -

-cl AllTests.c CuTest.c CuTestTest.c
-AllTests.exe
-
- -

This will run all the unit tests associated with CuTest and -print the output on the console. - -

For more details on how to use the library look at the README file included -with the distribution. - -

Contribute

- -

We hope you CuTest saves you time and helps you produce high quality -software. - -

If you find CuTest useful, let us know. Tell us what platform you are using -it on (Windows, Linux, etc), and what kinds of applications you are using it -with. - -

If you would like to contribute documentation or tutorials to this project -please send e-mail. - -
-
- -


- -Copyright © 2002-2003, Asim Jalis (asimjalis(nospam)gmail.com). -All rights reserved. - - - - -

-SourceForge.net Logo - - - diff --git a/externalTools/cutest/license.txt b/externalTools/cutest/license.txt deleted file mode 100644 index 5f053ba..0000000 --- a/externalTools/cutest/license.txt +++ /dev/null @@ -1,38 +0,0 @@ -NOTE - -The license is based on the zlib/libpng license. For more details see -http://www.opensource.org/licenses/zlib-license.html. The intent of the -license is to: - -- keep the license as simple as possible -- encourage the use of CuTest in both free and commercial applications - and libraries -- keep the source code together -- give credit to the CuTest contributors for their work - -If you ship CuTest in source form with your source distribution, the -following license document must be included with it in unaltered form. -If you find CuTest useful we would like to hear about it. - -LICENSE - -Copyright (c) 2003 Asim Jalis - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software in -a product, an acknowledgment in the product documentation would be -appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and must not -be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. diff --git a/externalTools/cutest/make-tests.sh b/externalTools/cutest/make-tests.sh deleted file mode 100644 index 3988c5e..0000000 --- a/externalTools/cutest/make-tests.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash - -# Auto generate single AllTests file for CuTest. -# Searches through all *.c files in the current directory. -# Prints to stdout. -# Author: Asim Jalis -# Date: 01/08/2003 - -if test $# -eq 0 ; then FILES=*.c ; else FILES=$* ; fi - -echo ' - -/* This is auto-generated code. Edit at your own peril. */ -#include -#include - -#include "CuTest.h" - -' - -cat $FILES | grep '^void Test' | - sed -e 's/(.*$//' \ - -e 's/$/(CuTest*);/' \ - -e 's/^/extern /' - -echo \ -' - -void RunAllTests(void) -{ - CuString *output = CuStringNew(); - CuSuite* suite = CuSuiteNew(); - -' -cat $FILES | grep '^void Test' | - sed -e 's/^void //' \ - -e 's/(.*$//' \ - -e 's/^/ SUITE_ADD_TEST(suite, /' \ - -e 's/$/);/' - -echo \ -' - CuSuiteRun(suite); - CuSuiteSummary(suite, output); - CuSuiteDetails(suite, output); - printf("%s\n", output->buffer); - CuStringDelete(output); - CuSuiteDelete(suite); -} - -int main(void) -{ - RunAllTests(); -} -' diff --git a/externalTools/cutest/style.css b/externalTools/cutest/style.css deleted file mode 100644 index 7759d5a..0000000 --- a/externalTools/cutest/style.css +++ /dev/null @@ -1,21 +0,0 @@ -BODY { - font-family: "Verdana,Arial,sans-serif"; - font-size: 10pt; -} -PRE.LIST { - background: #CFD9FF; - border: 1ex solid #AAAAE6; - padding: 1ex; -} - -PRE.SNIP { - background: #CFD9FF; - padding: 1ex; -} - -PRE.CONSOLE { - color: #CCCCCC; - background: #000000; - font-family: "Courier New,Courier"; - padding: 1ex; -} diff --git a/externalTools/quicktree_1.1/Makefile b/externalTools/quicktree_1.1/Makefile deleted file mode 100755 index 3214626..0000000 --- a/externalTools/quicktree_1.1/Makefile +++ /dev/null @@ -1,55 +0,0 @@ - -BIN = ./bin -SRC = ./src -INC = ./include -OBJ = ./obj - -COMMON = $(OBJ)/align.o \ - $(OBJ)/cluster.o \ - $(OBJ)/distancemat.o \ - $(OBJ)/options.o \ - $(OBJ)/util.o \ - $(OBJ)/sequence.o - -QUICKTREEOBJ = $(COMMON) $(OBJ)/quicktree.o $(OBJ)/buildtree.o $(OBJ)/tree.o - -CFLAGS += -c -I$(INC) -O3 -Wall - -LDFLAGS += -g - -all: $(BIN)/quicktree - -quicktree : $(BIN)/quicktree - -$(BIN)/quicktree : $(QUICKTREEOBJ) - $(CC) $(DLFLAGS) -o $@ $(QUICKTREEOBJ) -lm - -$(OBJ)/quicktree.o : $(SRC)/quicktree.c - $(CC) $(CFLAGS) $(CPPFLAGS) -o $(OBJ)/quicktree.o $(SRC)/quicktree.c - -$(OBJ)/align.o : $(SRC)/align.c $(INC)/align.h - $(CC) $(CFLAGS) $(CPPFLAGS) -o $(OBJ)/align.o $(SRC)/align.c - -$(OBJ)/buildtree.o : $(SRC)/buildtree.c $(INC)/buildtree.h - $(CC) $(CFLAGS) $(CPPFLAGS) -o $(OBJ)/buildtree.o $(SRC)/buildtree.c - -$(OBJ)/cluster.o : $(SRC)/cluster.c $(INC)/cluster.h - $(CC) $(CFLAGS) $(CPPFLAGS) -o $(OBJ)/cluster.o $(SRC)/cluster.c - -$(OBJ)/distancemat.o : $(SRC)/distancemat.c $(INC)/distancemat.h - $(CC) $(CFLAGS) $(CPPFLAGS) -o $(OBJ)/distancemat.o $(SRC)/distancemat.c - -$(OBJ)/sequence.o : $(SRC)/sequence.c $(INC)/sequence.h - $(CC) $(CFLAGS) $(CPPFLAGS) -o $(OBJ)/sequence.o $(SRC)/sequence.c - -$(OBJ)/tree.o : $(SRC)/tree.c $(INC)/tree.h - $(CC) $(CFLAGS) $(CPPFLAGS) -o $(OBJ)/tree.o $(SRC)/tree.c - -$(OBJ)/util.o : $(SRC)/util.c $(INC)/util.h - $(CC) $(CFLAGS) $(CPPFLAGS) -o $(OBJ)/util.o $(SRC)/util.c - -$(OBJ)/options.o : $(SRC)/options.c $(INC)/options.h - $(CC) $(CFLAGS) $(CPPFLAGS) -o $(OBJ)/options.o $(SRC)/options.c - -clean: - rm -rf $(OBJ)/*.o diff --git a/externalTools/quicktree_1.1/README b/externalTools/quicktree_1.1/README deleted file mode 100644 index 7d6205c..0000000 --- a/externalTools/quicktree_1.1/README +++ /dev/null @@ -1,45 +0,0 @@ - -About QuickTree -=============== - -QuickTree is an efficient implementation of the Neighbor-Joining -algorithm, capable of reconstructing phylogenies from huge alignments in -time less than the age of the universe. - -QuickTree 1.1 -============= - -Version 1.1 contains some speed-ups and small bug-fixes from version 1.0. - - -Installing QuickTree -==================== - -QuickTree isi written in ANSI C and should complile and run on a number -of different platforms. "make quicktree" from this directory should -compile the program and place the executable in ./bin. - - -Using QuickTree -=============== - -quicktree -h gives a list of options. - -QuickTree accepts both distance matrix and multiple-sequence-aligment -inputs. The former should be in PHYLIP format. The latter should be in -Stockholm format, which is the native alignment format for the Pfam -database. Alignments in various formats can be converted to Stockholm -format with the sreformat program, which is part of the HMMer package by -Sean Eddy (hmmer.wustl.edu). - -The tress are written to stdout, in the Newick/Hew Hampshire format -use by PHYLIP and many other programs. - - -Contact -======= - -Any problems, please contact klh@sanger.ac.uk - -Kevin Howe, 2002 - diff --git a/externalTools/quicktree_1.1/bin/.gitignore b/externalTools/quicktree_1.1/bin/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/externalTools/quicktree_1.1/include/align.h b/externalTools/quicktree_1.1/include/align.h deleted file mode 100644 index 3e9da7a..0000000 --- a/externalTools/quicktree_1.1/include/align.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Last edited: Aug 27 16:31 1999 (klh) */ -/********************************************************************** - ** FILE: align.h - ** NOTES: - ** Functions and types for the manipulation of multiple sequence - ** alignments -**********************************************************************/ - -#ifndef _ALIGN -#define _ALIGN - -#include -#include -#include - -#include "sequence.h" -#include "util.h" - -#define RES_BLOCKSIZE 20 -#define SEQ_BLOCKSIZE 10 -#define MAX_LINE_LEN 4096 - -/******************* structure definitions ****************************/ - -struct Alignment { - unsigned int numseqs; - unsigned int length; - struct Sequence **seqs; -}; - -/********************** function prototypes ***************************/ - -/********************************************************************** - FUNCTION: free_Alignment - DESCRIPTION: - Frees the memory used by the given alignment - ARGS: - An Alignment - RETURNS: A null pointer - NOTES: - **********************************************************************/ -void *free_Alignment( struct Alignment *); - - -/********************************************************************** - FUNCTION: read_MUL_Alignment - DESCRIPTION: - Reads in a muliple alignment from the given file handle and returns - it - ARGS: - A file handle - RETURNS: A number denoting the status: - A pointer to the struct Alignment object created, or NULL of there - was an error parsing the file - NOTES: It is assumed that the aligment file is in Pfam (MUL) format. - Garbage results should be expected if the input file is not in this - format - - The function allocates all the memory necessary for the - alignment. The caller should call free_Alignment (align.h) to - free this memory when the alignment is no longer needed - **********************************************************************/ -struct Alignment *read_MUL_Alignment( FILE * ); - - -/********************************************************************** - FUNCTION: read_Stockholm_Alignment - DESCRIPTION: - This function fills a simple alignment structure from an - file assumed to be in Stockholm format. At this stage, I am ignoring - all mark-up information (all lines beginning with '#' are ignored). - The function also allows for wrapped alignments. Note that Pfam - alignments in MUL format will be handled correctly by this function - ARGS: - FILE * - RETURNS: struct Alignment (align.h) - NOTES: - **********************************************************************/ -struct Alignment *read_Stockholm_Alignment( FILE *); - - - -/********************************************************************** - FUNCTION: write_MUL_Alignment - DESCRIPTION: - Prints a rep. of the alignment to the given handle (in MUL format) - ARGS: - FILE * - struct Alignment (align.h) - RETURNS: struct Alignment (align.h) - NOTES: - **********************************************************************/ -void write_MUL_Alignment( FILE *, struct Alignment *); - -#endif - diff --git a/externalTools/quicktree_1.1/include/aln2dist.h b/externalTools/quicktree_1.1/include/aln2dist.h deleted file mode 100644 index cfb4652..0000000 --- a/externalTools/quicktree_1.1/include/aln2dist.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Last edited: Aug 24 14:46 1999 (klh) */ -/*********************************************************************** - ** FILE: aln2dist.h - ** NOTES: - ** This program produces a distance matrix in phylip format for the - ** given alignment file. The optional -k flag is used to determine - ** whether Kimura's tranlation is used to hopefully obtain more - ** accurate distances. The matrix is written to stdout - ***********************************************************************/ - -#ifndef _ALN2DIST -#define _ALN2DIST - -#include "options.h" -#include "util.h" -#include "align.h" -#include "cluster.h" - - -/********************** function prototypes ***************************/ - - -/********************************************************************* - FUNCTION: generate_matrix_matrixmaker - DESCRIPTION: - Given a fule handle to an alignment, creates and prints a - distance matrix for the sequences in the alignment in phylip format - to stdout - RETURNS: void - ARGS: - An open alignment FILE - NOTES: - *********************************************************************/ -void generate_DistanceMatrix_matrixmaker( FILE * ); - -#endif diff --git a/externalTools/quicktree_1.1/include/aln2tree.h b/externalTools/quicktree_1.1/include/aln2tree.h deleted file mode 100644 index c8588c9..0000000 --- a/externalTools/quicktree_1.1/include/aln2tree.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Last edited: Aug 24 14:45 1999 (klh) */ -/*********************************************************************** - ** FILE: aln2tree.h - ** NOTES: - ** This program constructs a phylogenetic tree from a given align- - ** ment file. The process comprises of two phases: - ** 1. Construction of a distance matrix. Here, the optional -k - ** is used to determine whether Kimura's tranlation is used to - ** hopefully obtain more accurate distance - ** 2. The construction of the tree. It is printed in New-Hampshire - ** format to standard output - ***********************************************************************/ - -#ifndef _ALN2TREE -#define _ALN2TREE - -#include "options.h" -#include "util.h" -#include "align.h" -#include "cluster.h" -#include "buildtree.h" - -/********************** function prototypes ***************************/ - - -/********************************************************************* - FUNCTION: maketree_treemaker - DESCRIPTION: - Given a fule handle to an alignment, creates and prints a neighbour - joining phlogenetic tree for the sequences in the alignment - RETURNS: void - ARGS: - A file handle to an alignment (should be in MUL format); - NOTES: - *********************************************************************/ -void maketree_treemaker( FILE * ); - - -#endif diff --git a/externalTools/quicktree_1.1/include/buildtree.h b/externalTools/quicktree_1.1/include/buildtree.h deleted file mode 100644 index e6fdd5b..0000000 --- a/externalTools/quicktree_1.1/include/buildtree.h +++ /dev/null @@ -1,124 +0,0 @@ -/* Last edited: Aug 24 14:28 1999 (klh) */ -/********************************************************************** - ** FILE: buildtree.h - ** NOTES: - ** Contains functions for building trees from distance matrices - ** (and vice versa) - **********************************************************************/ - -#ifndef _BUILDTREE -#define _BUILDTREE - -#include -#include "util.h" -#include "tree.h" -#include "cluster.h" - -/******************* structure definitions ****************************/ - - -/********************** function prototypes ***************************/ - - -/********************************************************************** - FUNCTION: export_distances_buildtree - DESCRIPTION: - Returns the distance matrix induced from the given tree, i.e. by summing - the branch paths between two nodes to obtain their distance - ARGS: - A Tree - A DistanceMatrix - RETURNS: - - NOTES: - This function does not create the memory for the distance matrix, it - merely fills in the given matrix - **********************************************************************/ -void export_distances_buildtree( struct Tree *, struct DistanceMatrix *); - - -/********************************************************************** - FUNCTION: find_path_buildtree - DESCRIPTION: - Given a leaf node, recursively calculates the branch-length distance - from the node to all other leaves in the tree, and places it in the - appropriate part of the DistanceMatrix - ARGS: - unsigned int (the node number from which we are finding all distances) - Tnode (the current node under consideration) - DistanceMatrix - Boolean array (to store which nodes have already been considered) - unsigned int (the size of this boolean array) - RETURNS: - NOTES: - **********************************************************************/ -void find_path_buildtree( unsigned int, - struct Tnode *, - struct DistanceMatrix *, - Distance, - unsigned int *); - - -/********************************************************************** - FUNCTION: leaf_find_buildtree - DESCRIPTION: - Finds the leaf nodes descended from the given interior node, and - calculates the distance from these nodes to all other nodes, by - way of another function call - ARGS: - Tnode - DistanceMatrix - Boolean array (to store which nodes have already been considered) - unsigned int (the size of this boolean array) - RETURNS: - NOTES: - **********************************************************************/ -void leaf_find_buildtree( struct Tnode *, - struct DistanceMatrix *, - unsigned int *, - unsigned int); - - - -/********************************************************************** - FUNCTION: neighbour_joining_buildtree - DESCRIPTION: - Returns a phylogenetic tree of the sequences in the - given alignment, using Saitou and Nei's neighbour-joining - algorithm - ARGS: - A ClusterGroup pointer (cluster.h) - Boolean, for whether to calc information needed for later bootstrapping - RETURNS: - A Tree (trees.h) - NOTES: The function allocates all the memory necessary for the tree. - The caller should call free_tree (tree.h) to free this memory when - the tree is no longer needed - **********************************************************************/ -struct Tree *neighbour_joining_buildtree( struct ClusterGroup *, - unsigned int); - - -/********************************************************************** - FUNCTION: UPGMA_buildtree - DESCRIPTION: - Returns a phylogenetic tree of the sequences in the - given alignment, using the Unweighted Pair-Group method based on - Arithmentic Averages (UPGMA) - ARGS: - A ClusterGroup pointer (cluster.h) - Boolean, for whether to calc information needed for later bootstrapping - RETURNS: - struct Tree (trees.h) - NOTES: The function allocates all the memory necessary for the tree. - The caller should call free_Tnode (tree.h) to free this memory when - the tree is no longer needed - - This algorithm produces a rooted tree; hence the returned Tree - will have the root in child[0]; child[1] and child[2] (used to - represent the trichotomy of unrooted trees) will be NULL - **********************************************************************/ -struct Tree *UPGMA_buildtree( struct ClusterGroup *, unsigned int); - - -#endif diff --git a/externalTools/quicktree_1.1/include/buildtree.h~ b/externalTools/quicktree_1.1/include/buildtree.h~ deleted file mode 100644 index 57084e7..0000000 --- a/externalTools/quicktree_1.1/include/buildtree.h~ +++ /dev/null @@ -1,124 +0,0 @@ -/* Last edited: Aug 24 14:28 1999 (klh) */ -/********************************************************************** - ** FILE: buildtree.h - ** NOTES: - ** Contains functions for building trees from distance matrices - ** (and vice versa) - **********************************************************************/ - -#ifndef _BUILDTREE -#define _BUILDTREE - -#include -#include "util.h" -#include "tree.h" -#include "cluster.h" - -/******************* structure definitions ****************************/ - - -/********************** function prototypes ***************************/ - - -/********************************************************************** - FUNCTION: export_distances_buildtree - DESCRIPTION: - Returns the distance matrix induced from the given tree, i.e. by summing - the branch paths between two nodes to obtain their distance - ARGS: - A Tree - A DistanceMatrix - RETURNS: - - NOTES: - This function does not create the memory for the distance matrix, it - merely fills in the given matrix - **********************************************************************/ -void export_distances_buildtree( struct Tree *, struct DistanceMatrix *); - - -/********************************************************************** - FUNCTION: find_path_buildtree - DESCRIPTION: - Given a leaf node, recursively calculates the branch-length distance - from the node to all other leaves in the tree, and places it in the - appropriate part of the DistanceMatrix - ARGS: - unsigned int (the node number from which we are finding all distances) - Tnode (the current node under consideration) - DistanceMatrix - Boolean array (to store which nodes have already been considered) - unsigned int (the size of this boolean array) - RETURNS: - NOTES: - **********************************************************************/ -void find_path_buildtree( unsigned int, - struct Tnode *, - struct DistanceMatrix *, - float, - unsigned int *); - - -/********************************************************************** - FUNCTION: leaf_find_buildtree - DESCRIPTION: - Finds the leaf nodes descended from the given interior node, and - calculates the distance from these nodes to all other nodes, by - way of another function call - ARGS: - Tnode - DistanceMatrix - Boolean array (to store which nodes have already been considered) - unsigned int (the size of this boolean array) - RETURNS: - NOTES: - **********************************************************************/ -void leaf_find_buildtree( struct Tnode *, - struct DistanceMatrix *, - unsigned int *, - unsigned int); - - - -/********************************************************************** - FUNCTION: neighbour_joining_buildtree - DESCRIPTION: - Returns a phylogenetic tree of the sequences in the - given alignment, using Saitou and Nei's neighbour-joining - algorithm - ARGS: - A ClusterGroup pointer (cluster.h) - Boolean, for whether to calc information needed for later bootstrapping - RETURNS: - A Tree (trees.h) - NOTES: The function allocates all the memory necessary for the tree. - The caller should call free_tree (tree.h) to free this memory when - the tree is no longer needed - **********************************************************************/ -struct Tree *neighbour_joining_buildtree( struct ClusterGroup *, - unsigned int); - - -/********************************************************************** - FUNCTION: UPGMA_buildtree - DESCRIPTION: - Returns a phylogenetic tree of the sequences in the - given alignment, using the Unweighted Pair-Group method based on - Arithmentic Averages (UPGMA) - ARGS: - A ClusterGroup pointer (cluster.h) - Boolean, for whether to calc information needed for later bootstrapping - RETURNS: - struct Tree (trees.h) - NOTES: The function allocates all the memory necessary for the tree. - The caller should call free_Tnode (tree.h) to free this memory when - the tree is no longer needed - - This algorithm produces a rooted tree; hence the returned Tree - will have the root in child[0]; child[1] and child[2] (used to - represent the trichotomy of unrooted trees) will be NULL - **********************************************************************/ -struct Tree *UPGMA_buildtree( struct ClusterGroup *, unsigned int); - - -#endif diff --git a/externalTools/quicktree_1.1/include/cluster.h b/externalTools/quicktree_1.1/include/cluster.h deleted file mode 100644 index cdfae80..0000000 --- a/externalTools/quicktree_1.1/include/cluster.h +++ /dev/null @@ -1,174 +0,0 @@ -/* Last edited: Aug 25 15:19 1999 (klh) */ -/********************************************************************** - ** FILE: cluster.h - ** NOTES: - ** A DistanceMatrix should always be part of a Cluster - ** It makes no sense to have a set of pairwise distances without the - ** associated sequences (even if we just store their names) - **********************************************************************/ - -#ifndef _CLUSTER -#define _CLUSTER - -#include "sequence.h" -#include "distancemat.h" - - - -/******************* structure definitions ****************************/ - -struct Cluster { - unsigned int clustersize; - struct Sequence **members; - struct Sequence *consensus; - struct DistanceMatrix *matrix; -}; - - -/* - Clusters contain groups of identical sequence. I intend to investigate - methods where clusters contain groups of similar (not necessarily - identical) sequences. The DistanceMatric field, although not currently - used, will allow for the building of trees from these clusters -*/ - - -struct ClusterGroup { - unsigned int numclusters; - struct Cluster **clusters; - struct DistanceMatrix *matrix; -}; - - -/********************** function prototypes ***************************/ - - - -/********************************************************************* - FUNCTION: alignment_to_ClusterGroup - DESCRIPTION: - This function returns a ClusterGroup, given an Alignment. - if the secind arg is true, In doing indentical sequences in the - alignment are merged. If bootstrapping is required, the consensus - alignment can be extracted from the ClusterGroup using - get_consensus_from_ClusterGroup - RETURNS: struct ClusterGroup - ARGS: - 1. A source Alignment pointer - 2. A boolean specifying whether duplicate sequences should be - merged. - NOTES: -*********************************************************************/ -struct ClusterGroup *alignment_to_ClusterGroup( struct Alignment *,unsigned int); - -/********************************************************************* - FUNCTION: clone_Cluster - DESCRIPTION: - This function makes a complete copy of the given Cluster - and returns it - RETURNS: struct Cluster * - ARGS: - struct Cluster * - NOTES: - *********************************************************************/ -struct Cluster *clone_Cluster( struct Cluster *); - -/********************************************************************* - FUNCTION: consensus_aln_from_ClusterGroup - DESCRIPTION: - This function creates an alignment by taking the consensus - sequences from each Cluster in the given ClusterGroup - RETURNS: struct ClusterGroup - ARGS: - 1. A source Alignment pointer - 2. A boolean specifying whether duplicate sequences should be - merged. - NOTES: -*********************************************************************/ -struct Alignment *consensus_aln_from_ClusterGroup( struct ClusterGroup *); - -/********************************************************************* - FUNCTION: empty_Cluster - DESCRIPTION: - This function handles the simple task of allocating the space - for a new Cluster. - RETURNS: struct Cluster * - ARGS: - NOTES: - *********************************************************************/ -struct Cluster *empty_Cluster( void ); - -/********************************************************************* - FUNCTION: empty_ClusterGroup - DESCRIPTION: - This function handles the simple task of allocating the space - for a new ClusterGroup - RETURNS: struct Cluster * - ARGS: - NOTES: - *********************************************************************/ -struct ClusterGroup *empty_ClusterGroup( void ); - -/********************************************************************* - FUNCTION: free_Cluster - DESCRIPTION: - This function releases the memory used by this Cluster and all of its - members - RETURNS: A null pointer - ARGS: - struct Cluster * - NOTES: - *********************************************************************/ -void *free_Cluster( struct Cluster *); - -/********************************************************************* - FUNCTION: free_ClusterGroup - DESCRIPTION: - This function releases the memory used by this Cluster and all of its - members - RETURNS: A null pointer - ARGS: - struct Cluster * - NOTES: - *********************************************************************/ -void *free_ClusterGroup( struct ClusterGroup *); - -/********************************************************************* - FUNCTION: merge_Cluster - DESCRIPTION: - Adds the sequences in second arg to first arg, freeing the second - arg, returning the result of this freeing (hopefully NULL); - RETURNS: The result of freeing the second cluster (NULL if all is well) - ARGS: - Destination Cluster *, - Source Cluster * - NOTES: - *********************************************************************/ -void *merge_Cluster( struct Cluster *, struct Cluster *); - -/********************************************************************* - FUNCTION: single_Sequence_Cluster - DESCRIPTION: - This function handles the simple task of allocating the space - for a new Cluster with the single given Sequence. - RETURNS: struct Cluster * - ARGS: - A pointer to a Sequence, or NULL for an empty Cluster - NOTES: - *********************************************************************/ -struct Cluster *single_Sequence_Cluster( struct Sequence *); - -/********************************************************************* - FUNCTION: single_Cluster_ClusterGroup - DESCRIPTION: - This function takes the given cluster and very simlpy makes a - single-Cluster ClusterGroup from it - RETURNS: struct ClusterGroup * - ARGS: - A pointer to a Cluster - NOTES: - *********************************************************************/ -struct ClusterGroup *single_Cluster_ClusterGroup( struct Cluster *); - - -#endif diff --git a/externalTools/quicktree_1.1/include/dist2tree.h b/externalTools/quicktree_1.1/include/dist2tree.h deleted file mode 100644 index fe4f1bd..0000000 --- a/externalTools/quicktree_1.1/include/dist2tree.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Last edited: Aug 25 15:33 1999 (klh) */ -/********************************************************************** - ** FILE: dist2tree.h - ** NOTES: - ** This program can be used to generate neighbour-joining - ** trees given a distance matrix file. - ** The matrix file should be in phylip format; the application was - ** originally coded to compare the efficiency of the writer's - ** implementation of neighbourjoining with that of phylip's - ** 'neighbor' program. The tree is writtento stdout in New Hants - ** format. - **********************************************************************/ - - -#ifndef _DIST2TREE -#define _DIST2TREE - -#include "align.h" -#include "options.h" -#include "util.h" -#include "cluster.h" -#include "buildtree.h" - - -/********************** function prototypes ***************************/ - -/********************************************************************* - FUNCTION: maketree_neighbourjoin - DESCRIPTION: - Given a file handle to a distance matrix, creates and prints a neighbour - joining phlogenetic tree for the sequences in the alignment - RETURNS: void - ARGS: - A file handle to a distance matrix (in 'phylip' format) - NOTES: - *********************************************************************/ -void maketree_neighbourjoin( FILE * ); - - -#endif diff --git a/externalTools/quicktree_1.1/include/distancemat.h b/externalTools/quicktree_1.1/include/distancemat.h deleted file mode 100644 index 1c28bb5..0000000 --- a/externalTools/quicktree_1.1/include/distancemat.h +++ /dev/null @@ -1,189 +0,0 @@ -/* Last edited: Aug 25 15:25 1999 (klh) */ -/********************************************************************** - ** FILE: distancemat.h - ** NOTES: - ** Functions and types for the manipulation of Distance Matrices - **********************************************************************/ - -#ifndef _DISTANCEMAT -#define _DISTANCEMAT - -#include - -#include "util.h" -#include "align.h" -#include "time.h" - - -/******************* structure definitions ****************************/ - -typedef float Distance; - -struct DistanceMatrix { - Distance **data; - int size; -}; - - -/********************** function prototypes ***************************/ - - -/********************************************************************* - FUNCTION: calc_DistanceMatrix - DESCRIPTION: - Produces a distance matrix from the given multiple alignment - RETURNS: struct DistanceMatrix - ARGS: - A DistanceMatrix to fill in - A multiple alignment - A boolean indicating whether or not random columns should be used - for purposes of bootstrapping - A boolean indicating whether the Kimura distance adjustment is to - be used or not. - NOTES: - 0. the given DistanceMatrix and Alignment should be of the same order - - 1. The matrix produced is in bottom-left triangular format; don't you - go trying to access that top-right section (I'm warning you...) - - 2. At the moment, the function calculates distance based on sequence - identity, using Kimura's function if that option is raised. - - 3. If use_rand_cols is true, then the matrix is constructed using - random sampling of columns, for the purposes of bootstrapping. At - the moment, the native function 'rand' is used to do this, suitable - seeded by time (by the caller). This may prove unsatisfactory... - - 4. Where no information is available to determine the distance - between two sequences, a value of twice the maximum observed - distance is assigned (inspiration from ISMB99 poster by Huson, - Smith and Warnow). - - *********************************************************************/ -void calc_DistanceMatrix(struct DistanceMatrix *, - struct Alignment *, - unsigned int, - unsigned int ); - -/********************************************************************* - FUNCTION: clone_DistanceMatrix - DESCRIPTION: - Produces a brand new DistanceMatrix, identical to the source - RETURNS: struct DistanceMatrix - ARGS: - A source distane matrix - NOTES: - 1. The matrix produced is in bottom-left triangular format; don't you - go trying to access that top-right section (I'm warning you...) - *********************************************************************/ -struct DistanceMatrix *clone_DistanceMatrix( struct DistanceMatrix *); - -/********************************************************************* - FUNCTION: empty_DistanceMatrix - DESCRIPTION: - Produces an empty distance matrixof the given size, uninitialised - RETURNS: struct DistanceMatrix - ARGS: - The size of the matrix to be created - NOTES: - 1. The matrix produced is in bottom-left triangular format; don't you - go trying to access that top-right section (I'm warning you...) - *********************************************************************/ -struct DistanceMatrix *empty_DistanceMatrix( unsigned int ); - -/********************************************************************* - FUNCTION: free_DistanceMatrix - DESCRIPTION: - Frees the memory for the given distance matrix - RETURNS: - ARGS: - struct DistanceMatrix * - NOTES: - *********************************************************************/ -void *free_DistanceMatrix( struct DistanceMatrix *); - -/********************************************************************** - FUNCTION: index_DistanceMatrix - DESCRIPTION: - indexes the given distance matrix with the given indices, - returning the appropraite distance. - RETURNS: distance (float) - ARGS: - A distance matrix * - row index - column index - NOTES: - This function is necessary to account for the fact that the distance - matrix may be implemented as a symmtrical or triangular matrix. - It therefore abstracts the internals of the distance matrix, at the - cost of a function call for each lookup (is this wise...?) - **********************************************************************/ -Distance index_DistanceMatrix( struct DistanceMatrix *, unsigned int, unsigned int ); - -/********************************************************************* - FUNCTION: print_DistanceMatrix - DESCRIPTION: - Prints the given distance matrix. - RETURNS: - ARGS: - struct DistanceMatrix * - NOTES: - A DistanceMatrix does not exist in isolation in practice but as - part of a Cluster (this is to maintain the tight coupling between - the matrix and the sequences for which it is expressing the distances). - Therefore, to read or write a useful distance - matrix (for compatibility with the phylip package for example) - use write_phylip_Cluster - *********************************************************************/ -void print_DistanceMatrix( FILE *handle, struct DistanceMatrix * ); - - -/********************************************************************* - FUNCTION: read_phylip_DistanceMatrix - DESCRIPTION: - This function creates a DistanceMatrix from the given input file. - It also crates a dummy alignment (sequences with just names) and - puts it in the given Alignment pointer - RETURNS: struct Cluster * - ARGS: - A file handle - A pointer to an Alignment pointer - NOTES: - The file is assumed to be the distance matrix file format used - by the phlip package: - - 4 - Name_1 0.0000 0.6776 0.6786 0.2342 - Name_2 0.6776 0.0000 0.1111 0.9999 - Name_3 0.6786 0.1111 0.0000 0.4444 - Name_4 0.2342 0.9999 0.4444 0.0000 - *********************************************************************/ -struct DistanceMatrix *read_phylip_DistanceMatrix( FILE *, struct Alignment **); - -/********************************************************************* - FUNCTION: write_phylip_DistanceMatrix - DESCRIPTION: - This function takes the given DistanceMatrix and writes it to the - given file handle in phylip format. The alignment is needed for the - Sequence names - format - RETURNS: - ARGS: - A file handle - A DistanceMatrix pointer (cluster.h) - An Alignment pointer - NOTES: - The file is written in the distance matrix file format used - by the phlip package: - - 4 - Name_1 0.0000 0.6776 0.6786 0.2342 - Name_1 0.6776 0.0000 0.1111 0.9999 - Name_1 0.6786 0.1111 0.0000 0.4444 - Name_1 0.2342 0.9999 0.4444 0.0000 -*********************************************************************/ - -void write_phylip_DistanceMatrix( FILE *, struct DistanceMatrix *, struct Alignment *); - - -#endif diff --git a/externalTools/quicktree_1.1/include/options.h b/externalTools/quicktree_1.1/include/options.h deleted file mode 100644 index ee872bc..0000000 --- a/externalTools/quicktree_1.1/include/options.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Last edited: Feb 1 15:25 2002 (klh) */ -/********************************************************************** - ** FILE: options.h - ** DESCRIPTION: - ** Rudimentary provision of command-line options - **********************************************************************/ - -#ifndef _GETOPTIONS -#define _GETOPTIONS - - -#include -#include - -#include "util.h" - - -/************************** constants *********************************/ - -#define NO_ARGS 0 -#define INT_ARG 1 -#define FLOAT_ARG 2 -#define CHAR_ARG 3 -#define STRING_ARG 4 - -/******************* structure definitions ****************************/ - -struct Option { - char *name; /* name of option, e.g. "-option" */ - unsigned int type; /* for typechecking, e.g. INT_ARG */ -}; - - -/******************* function prototypes ****************************/ - -/********************************************************************* - FUNCTION: get_option - DESCRIPTION: - Gets an option from the given command line - RETURNS: - 1, if a valid option was found - 0, if no valid option was found and option parsing is therefore - complete - ARGS: - NOTES: -*********************************************************************/ -unsigned int get_option(int, char **, struct Option *, unsigned int, - char *, unsigned int *, char **, char **); - - -#endif - diff --git a/externalTools/quicktree_1.1/include/sequence.h b/externalTools/quicktree_1.1/include/sequence.h deleted file mode 100644 index 6a1ebf5..0000000 --- a/externalTools/quicktree_1.1/include/sequence.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Last edited: Nov 15 12:24 1999 (klh) */ -/********************************************************************** - ** FILE: sequence.h - ** NOTES: - ** Functions and structures for the manipulation of protein - ** sequences. Only minimal functionality is needed - **********************************************************************/ - -#ifndef _SEQUENCE -#define _SEQUENCE - -#include -#include "util.h" - - -#define MAX_NAME_LENGTH 25 - -/******************* structure definitions ****************************/ - -struct Sequence { - unsigned int length; - char *name; - char *seq; - char *sec_struct; - char *surf_acc; - char *trans_mem; - char *post_prob; - char *lig_bind; -}; - -/********************** function prototypes ***************************/ - - -/********************************************************************** - FUNCTION: clone_Sequence - DESCRIPTION: - Performs a deep copy of the given Sequence and returns it - ARGS: - A Sequenced pointer (sequence.h) - RETURNS: - A pointer to a Sequence structure - NOTES: - **********************************************************************/ -struct Sequence *clone_Sequence( struct Sequence *); - -/********************************************************************** - FUNCTION: empty_Sequence - DESCRIPTION: - Creates and returns an new, empty Sequence object - ARGS: - RETURNS: - A pointer to a Sequence structure - NOTES: - **********************************************************************/ -struct Sequence *empty_Sequence( void ); - -/********************************************************************** - FUNCTION: free_Sequence - DESCRIPTION: - frees the memory occupied by the given Sequence reference - ARGS: - A pointer to a struct Sequence - RETURNS: - The NULL pointer - NOTES: - **********************************************************************/ -void *free_Sequence( struct Sequence *); - - -#endif diff --git a/externalTools/quicktree_1.1/include/tree.h b/externalTools/quicktree_1.1/include/tree.h deleted file mode 100644 index afa513b..0000000 --- a/externalTools/quicktree_1.1/include/tree.h +++ /dev/null @@ -1,390 +0,0 @@ -/* Last edited: Jun 21 12:03 2001 (klh) */ -/********************************************************************** - ** FILE: tree.h - ** NOTES: - ** Functions and types for the manipulation of trees - **********************************************************************/ - -#ifndef _TREE -#define _TREE - -#include - -#include "util.h" -#include "sequence.h" -#include "cluster.h" - -#define LINE_BUFFER_SIZE 40 - - -/******************* structure definitions ****************************/ - -/****************** - This structure represents a tree-node. Everything is self-explanatory, - except that much of the tree-building code relies upon a correspondence - between node-numbers of leaf nodes, and sequence/cluster numbers. This - is particulary important when re-constructing distance matrices from - trees, and for bootstrapping trees. This may be troublesome if a tree is - read in from a file... -******************/ - - -struct Tnode { - struct Tnode *left; - struct Tnode *right; - struct Tnode *parent; - double distance; - unsigned int nodenumber; - struct Cluster *clust; - unsigned int bootstrap; - unsigned int *child_ids; -}; - - -/*********************** - This structure represents an unrooted binary tree of three or more - nodes; Two node trees, although trivial, can be modelled by having - one of the three children as null. A rooted tree can be represented - by a Tnode only, or by having two of the children of the trichotomy - as NULL. -*************************/ - -struct Tree { - struct Tnode *child[3]; - unsigned int numnodes; -}; - - -/********************** function prototypes ***************************/ - -/********************************************************************* - FUNCTION: assign_nodesnumbers_Tnode - DESCRIPTION: - This function assigns node numbers to the internal nodes of the - given Tnode, starting from the given, and returns the next free - nodenumner - RETURNS: unsigned int - ARGS: - struct Tnode * (tree) - unsigned int (starting node number) - NOTES: - *********************************************************************/ -unsigned int assign_nodenumbers_Tnode( struct Tnode *, unsigned int); - - -/********************************************************************* - FUNCTION: clone_Tnode - DESCRIPTION: - This function makes a complete copy of the tree rooted at the given - node and returns it - RETURNS: Tnode * - ARGS: - struct Tnode * - NOTES: - *********************************************************************/ -struct Tnode *clone_Tnode( struct Tnode *); - -/********************************************************************* - FUNCTION: clone_Tree - DESCRIPTION: - This function makes a complete copy of the Tree and returns it - RETURNS: struct Tree * - ARGS: - struct Tree * - NOTES: - *********************************************************************/ -struct Tree *clone_Tree( struct Tree *); - - -/********************************************************************* - FUNCTION: compare_to_bootstrap_sample_Tnode - DESCRIPTION: - Updates the bootstrap values of the given Tnode, according to - the topology of the given sample Tnode - RETURNS: - ARGS: - Destination Tnode - Sample Tnode - The number of leaf nodes in each tree - Boolean for whether the tree is binary or not - NOTES: - This function assumes that the given trees have been created by - calling either neighbourjoin_buildtree or UPGMA_buildtree with - the bootstrap boolean arguement set to true. A fatal error results - if this is not the case. This is due to the fact that the information - needed for the tree comparisons is determined when the trees are - constructed - *********************************************************************/ -void compare_to_bootstrap_sample_Tnode( struct Tnode *, struct Tnode *, - unsigned int, unsigned int); - -/********************************************************************* - FUNCTION: empty_Tree - DESCRIPTION: - Creates and returns a tree with null nodes - RETURNS: struct Tree * (trees.h) - ARGS: - NOTES: - *********************************************************************/ -struct Tree *empty_Tree( void ); - -/********************************************************************* - FUNCTION: free_Tnode - DESCRIPTION: - This function releases the memory used by this Tnode and all of its - children - RETURNS: A null pointer - ARGS: - struct Tnode * - NOTES: - *********************************************************************/ -void *free_Tnode( struct Tnode *); - -/********************************************************************* - FUNCTION: free_Tree - DESCRIPTION: - This function releases the memory used br the Tnode chain in the - given Tree - RETURNS: A null pointer - ARGS: - struct Tree - NOTES: - *********************************************************************/ -void *free_Tree( struct Tree *); - -/********************************************************************* - FUNCTION: get_root_Tnode - DESCRIPTION: This function takes a three node tree (struct Tree), and - returns a Tnode as the 'root' of the tree. The root is inserted - somewhat arbitraily between the three top-level nodes - RETURNS: struct Tnode * - ARGS: struct Tree - NOTES: - The nodes of the given tree are cloned for use. This means - that the old tree is still available and safe on return, and must - be freed when finished with. The rooted tree returned by this - function must be freed by a call to free_Tnode_tree - *********************************************************************/ -struct Tree *get_root_Tnode( struct Tree * ); - -/********************************************************************* - FUNCTION: new_interior_Tnode (unsigned int) - DESCRIPTION: - This function handles the simple task of allocating the space - for a new interior (non-leaf) tree node, filling it with what it - knows, and returning it. - RETURNS: struct Tnode * (trees.h) - ARGS: - A integer to hold the node number. - NOTES: - This function s for creating internal nodes, which have no string - id but just a number identifier - *********************************************************************/ -struct Tnode *new_interior_Tnode( unsigned int ); - -/********************************************************************* - FUNCTION: new_leaf_Tnode (int, char *) - DESCRIPTION: - This function handles the simple task of allocating the space - for a new tree node, filling it with what it knows, and - returning it. - RETURNS: struct Tnode * (trees.h) - ARGS: - A integer to hold the sequence number associated with the node - The name of the node - NOTES: - This function is for creating leaf nodes, which have a name. - *********************************************************************/ -struct Tnode *new_leaf_Tnode( unsigned int, struct Cluster *); - -/********************************************************************* - FUNCTION: read_newhampshire_Tnode - DESCRIPTION: - Construct a Tnode from the given file handle - RETURNS: The total number of nodes constructed as a result of the call - ARGS: - File handle (assumed in New Hampshire format) - NOTES: - Numbering of internal nodes is abandoned in favour of giving leaf - nodes numbers from 0 to the number of leaves in the tree. This makes - them handy indices into a distance matrix for example - *********************************************************************/ -unsigned int read_newhampshire_Tnode( FILE *, struct Tnode **, - struct Tnode *, unsigned int); - -/********************************************************************* - FUNCTION: read_newhampshire_Tree - DESCRIPTION: - Constructs a tree from the given file handle - RETURNS: Tree * - ARGS: A handle to the file (assumed in New Hamshire format) - NOTES: - The convention that the numbering of the interior nodes starts - after all leaf nodes have been numbered is is violated with this - method; the numbering is performed in a bottom-up, left-to-right - fashion, so that the nodes in the left subtree all have number-ids - strictly less than those in the right subtree - - *********************************************************************/ -struct Tree *read_newhampshire_Tree( FILE *); - -/********************************************************************* - FUNCTION: scale_bootstraps_Tnode - DESCRIPTION: - This function traverses the given Tnode, dividing the bootstrap - values by the given number - RETURNS: - ARGS: - Tnode - A the number of bootstrap iterations that were performed - NOTES: - - *********************************************************************/ -void scale_bootstraps_Tnode( struct Tnode *, unsigned int); - - -/********************************************************************* - FUNCTION: scale_bootstraps_Tree - DESCRIPTION: - This function traverses the gieven tree, dividing the bootstrap - values by the given number - RETURNS: - ARGS: - Tree - A the number of bootstrap iterations that were performed - NOTES: - - *********************************************************************/ -void scale_bootstraps_Tree( struct Tree *, unsigned int); - - -/********************************************************************* - FUNCTION: update_bootstraps_Tree - DESCRIPTION: - Updates the bootstrap values of the destination Tree, according to - the topology of the given sample tree - RETURNS: - ARGS: - Destination tree - Sample tree - The number of leaf nodes in the trees - NOTES: - *********************************************************************/ -void update_bootstraps_Tree( struct Tree *, struct Tree *, unsigned int); - -/********************************************************************* - FUNCTION: update_bootstraps_Tnode - DESCRIPTION: - Updates the bootstrap values of the destination Tnode, according to - the topology of the given sample Tnode - RETURNS: - ARGS: - Destination Tnode - Sample Tnode - The number of leaf nodes in the tree - Boolean for whether the trees are binary or not - NOTES: - *********************************************************************/ -void update_bootstraps_Tnode( struct Tnode *, struct Tnode *, - unsigned int, unsigned int); - -/********************************************************************* - FUNCTION: write_clustering_data_Tnode - DESCRIPTION: - This routine prints a text description of the clustering details - of the given Tnode. It was written for the old implementation, - where leaves were named "leaf_1", "leaf_2" etc, and it would - often be the case that each leaf would contain several sequences. - With the current implementation, this function is not used; a - new-hampshire output of each cluster is printed in-situ, preserving - sequence names from the original alignment - RETURNS: - ARGS: - File handle - TNode * - NOTES: - *********************************************************************/ -void write_clustering_data_Tnode( FILE *, struct Tnode *); - - -/********************************************************************* - FUNCTION: write_debug_Tnode - DESCRIPTION: - Writes the given Tnode to the give file handle in 'debug' format - RETURNS: - ARGS: - File handle - TNode * - Integer offset - NOTES: - *********************************************************************/ -void write_debug_Tnode( FILE *, struct Tnode *, unsigned int); - -/********************************************************************* - FUNCTION: write_debug_Tree - DESCRIPTION: - prints the given Tree in a format suitable for debugging - RETURNS: - ARGS: - File handle - Tree * - NOTES: - *********************************************************************/ -void write_debug_Tree( FILE *, struct Tree *); - -/********************************************************************* - FUNCTION: write_MUL_flattened_Tnode - DESCRIPTION: - Prints the given tree as a MUL format alignment, with the sequences - in 'tree order' - RETURNS: - ARGS: - File handle - TNode * - NOTES: - *********************************************************************/ -void write_MUL_flattened_Tnode( FILE *, struct Tnode *); - -/********************************************************************* - FUNCTION: write_MUL_flattened_Tree - DESCRIPTION: - Prints the given tree as a MUL format sequence alignment, with - the sequences in 'tree order' - RETURNS: - ARGS: - File handle - Tree * - NOTES: - *********************************************************************/ -void write_MUL_flattened_Tree( FILE *, struct Tree *); - - -/********************************************************************* - FUNCTION: write_newhampshire_Tnode - DESCRIPTION: - prints the given Tree in 'New Hampshire' text format to the given - file handle - RETURNS: - ARGS: - File handle - TNode * - NOTES: - *********************************************************************/ -void write_newhampshire_Tnode( FILE *, struct Tnode *, unsigned int); - -/********************************************************************* - FUNCTION: write_newhampshire_Tree - DESCRIPTION: - prints the given Tnode in 'New Hampshire' text format to the given - file handle - RETURNS: - ARGS: - File handle - TNode * - NOTES: - *********************************************************************/ -void write_newhampshire_Tree( FILE *, struct Tree *, unsigned int); - - - -#endif diff --git a/externalTools/quicktree_1.1/include/util.h b/externalTools/quicktree_1.1/include/util.h deleted file mode 100644 index 33af493..0000000 --- a/externalTools/quicktree_1.1/include/util.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Last edited: Feb 1 15:32 2002 (klh) */ -/********************************************************************** - ** FILE: util.h - ** NOTES: - ** This file contains general utiliy functions used throughout the - ** application, such as those for memory management and error - ** messaging. I have used it as a place to put other general stuff - ** until I have somewhere better to put it. - **********************************************************************/ - -#ifndef _UTIL -#define _UTIL - -#include -#include -#include -#include - - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - - -/********************** function prototypes ***************************/ - -/********************************************************************* - FUNCTION: calloc_util - DESCRIPTION: - A wrapper for the stdlib.h function calloc; exits if memory cannot - be allocated - RETURNS: A generic pointer to the reallocated memory - ARGS: - The number of bytes to be allocated - NOTES: - *********************************************************************/ -void *calloc_util( size_t, size_t ); - - -/********************************************************************* - FUNCTION: malloc_util - DESCRIPTION: - A wrapper for the stdlib.h function malloc; exits if memory cannot - be allocated - RETURNS: A generic pointer to the reallocated memory - ARGS: - The number of bytes to be allocated - NOTES: - *********************************************************************/ -void *malloc_util( size_t ); - - -/********************************************************************* - FUNCTION: realloc_util - DESCRIPTION: - A wrapper for the stdlib.h function realloc; exits if memory cannot - be allocated - RETURNS: A generic pointer to the reallocated memory - ARGS: - A pointer to the memory to be reallocated - The number of bytes to be allocated - NOTES: - *********************************************************************/ -void *realloc_util( void *, size_t ); - - -/********************************************************************* - FUNCTION: free_util - DESCRIPTION: - A wrapper for the stdlib.h function free; warns if the free could - not be performed - RETURNS: A (hopefully null) pointer - ARGS: - A pointer to the memory to be deallocated - NOTES: - *********************************************************************/ -void *free_util( void * ); - - -/********************************************************************* - FUNCTION: fatal_util - DESCRIPTION: - Prints the given formatted error message and exits - RETURNS: - ARGS: - A format string + args, c.f. printf - NOTES: - *********************************************************************/ -void fatal_util( char *, ... ); - - -/********************************************************************* - FUNCTION: warning_util - DESCRIPTION: - Prints the given formatted warning to stderr - RETURNS: - ARGS: - A format string + args, c.f. printf - NOTES: - *********************************************************************/ -void warning_util( char *, ... ); - - -#endif diff --git a/externalTools/quicktree_1.1/obj/.gitignore b/externalTools/quicktree_1.1/obj/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/externalTools/quicktree_1.1/src/align.c b/externalTools/quicktree_1.1/src/align.c deleted file mode 100644 index e24de91..0000000 --- a/externalTools/quicktree_1.1/src/align.c +++ /dev/null @@ -1,347 +0,0 @@ -/* Last edited: Feb 1 15:35 2002 (klh) */ -/********************************************************************** - ** FILE: align.c - ** NOTES: - ** Functions for the manipulation of multiple sequence - ** alignments -**********************************************************************/ - -#include "align.h" - - -static char *comment = "#"; -static char *whitespace = " \t\r\n"; -static char *terminator = "//"; - -/********************************************************************** - FUNCTION: free_Alignment - DESCRIPTION: - Frees the memory used by the given alignment - ARGS: - An Alignment - RETURNS: A null pointer - NOTES: -**********************************************************************/ -void *free_Alignment( struct Alignment *al ) { - unsigned int i; - - if (al != NULL) { - if (al->seqs != NULL) { - for( i=0; i < al->numseqs; i++) { - al->seqs[i] = free_Sequence( al->seqs[i] ); - } - al->seqs = free_util( al->seqs ); - } - al = free_util( al ); - } - return al; -} - - - -/********************************************************************** - FUNCTION: read_MUL_Alignment - DESCRIPTION: - Reads in a muliple alignment from the given file handle and returns - it - ARGS: - A file handle - RETURNS: A number denoting the status: - A pointer to the struct Alignment object created, or NULL of there - was an error parsing the file - NOTES: It is assumed that the aligment file is in Pfam (MUL) format. - Garbage results should be expected if the input file is not in this - format - - The function allocates all the memory necessary for the - alignment. The caller should call free_Alignment (align.h) to - free this memory when the alignment is no longer needed - **********************************************************************/ - -struct Alignment *read_MUL_Alignment( FILE *stream ) { - struct Alignment *aln; - unsigned int index = 0; - char tempname[MAX_NAME_LENGTH]; - int c; - - aln = (struct Alignment *) malloc_util( sizeof( struct Alignment )); - aln->numseqs = 0; - aln->seqs = NULL; - aln->length = 0; - - - while (( c = fgetc(stream)) != EOF) { - if (aln->numseqs % SEQ_BLOCKSIZE == 0) { - /* we need to allocate some more memory. But is it a malloc or realloc ? */ - - if (aln->numseqs == 0) { - aln->seqs = (struct Sequence **) malloc_util( SEQ_BLOCKSIZE * sizeof( struct Sequence *)); - } - else { - aln->seqs = (struct Sequence **) - realloc_util( aln->seqs, (aln->numseqs + SEQ_BLOCKSIZE) * sizeof( struct Sequence *)); - } - } - - index = 0; - while (! isspace(c) ) { - tempname[index++] = c; - c = fgetc(stream); - } - tempname[index] = '\0'; - while ( isspace(c = fgetc(stream)) ); - - - aln->seqs[aln->numseqs] = empty_Sequence(); - aln->seqs[aln->numseqs]->name = (char *) malloc_util( MAX_NAME_LENGTH * sizeof(char)); - strcpy(aln->seqs[aln->numseqs]->name, tempname); - - index = 0; - do { - if (index % RES_BLOCKSIZE == 0) { - /* we need to allocate some more memory. But is it a malloc or realloc ? */ - if (index == 0) { - aln->seqs[aln->numseqs]->seq = (char *) malloc_util( RES_BLOCKSIZE * sizeof(char)); - } - else { - aln->seqs[aln->numseqs]->seq = (char *) - realloc_util( aln->seqs[aln->numseqs]->seq, (index + RES_BLOCKSIZE) * sizeof(char)); - } - } - if (! isspace(c) ) - aln->seqs[aln->numseqs]->seq[index++] = c; - c = fgetc(stream); - - } while ( c != '\n' && c != EOF); - - /* Since we now know the length of the sequence, we can do a bit of resizing */ - - if (aln->numseqs == 0 || index < aln->length) { - /* The first sequence is the trend setter */ - aln->length = index; - } - /* First, resize the current sequence */ - aln->seqs[aln->numseqs]->seq = (char *) - realloc_util( aln->seqs[aln->numseqs]->seq, aln->length * sizeof(char)); - - /* if we reduced the aligment length, The earlier sequences are too big; - Since we will only read up to the length of the smallest sequence, this - will only prove a problem if we run out of memory; however, if the user - given non-flused alignments, then they are asking for everything they get... - */ - - aln->numseqs++; - - } - - /* now we can resize the seq array, and all the actual sequences themselves; this resizing - will only save significant memory if a non-flush alignment has been given. Is it worth - it? Well, we have to set the length of each sequence, so may as well do it while we are - here*/ - - aln->seqs = (struct Sequence **) realloc_util( aln->seqs, aln->numseqs * sizeof( struct Sequence *)); - for (index=0; index < aln->numseqs; index++) { - aln->seqs[index]->length = aln->length; - aln->seqs[index]->seq = (char *) - realloc_util( aln->seqs[index]->seq, aln->length * sizeof(char)); - } - - return aln; -} - - - -/********************************************************************** - FUNCTION: write_MUL_Alignment - DESCRIPTION: - Prints a rep. of the alignment to the given handle (in MUL format) - ARGS: - FILE * - struct Alignment (align.h) - RETURNS: struct Alignment (align.h) - NOTES: - **********************************************************************/ - -void write_MUL_Alignment( FILE *handle, struct Alignment *al ) { - unsigned int i,j; - - for( i=0; i < al->numseqs; i++ ) { - fprintf( handle, "%-24s ", al->seqs[i]->name); - for( j=0; j < al->length; j++) { - fprintf( handle, "%c", al->seqs[i]->seq[j]); - } - fprintf( handle, "\n"); - } - fflush( handle ); - -} - - - -/********************************************************************** - FUNCTION: read_Stockholm_Alignment - DESCRIPTION: - This function fills a simple alignment structure from an - file assumed to be in Stockholm format. At this stage, I am ignoring - all mark-up information (all lines beginning with '#' are ignored). - The function also allows for wrapped alignments. Note that Pfam - alignments in MUL format will be handled correctly by this function - ARGS: - FILE * - RETURNS: struct Alignment (align.h) - NOTES: - **********************************************************************/ - -struct Alignment *read_Stockholm_Alignment( FILE *handle ) { - struct Alignment *aln; - - char *line = (char *) malloc_util( MAX_LINE_LEN * sizeof(char) ); - unsigned int lineAllocSize = MAX_LINE_LEN; - char *name_ptr = NULL; - char *seq_ptr = NULL; - - unsigned int i, j; - unsigned int numblocks = 0; - unsigned int thisseq = 0; - unsigned int last_idx = 0; - unsigned int got_line = 0; - unsigned int saw_blank_line = 0; - - aln = (struct Alignment *) malloc_util( sizeof( struct Alignment )); - aln->numseqs = 0; - aln->seqs = NULL; - aln->length = 0; - - numblocks = 0; - thisseq = 0; - - /* skip to the start of the first block */ - got_line = 0; - - do { - if (fgets(line, lineAllocSize, handle) == NULL) - break; - else { - if (strchr(line, '\n') == NULL) { /* did not read whole line! */ - do { - lineAllocSize += MAX_LINE_LEN; - line = (char *) realloc_util( line, lineAllocSize * sizeof(char) ); - } while (fgets(line + lineAllocSize - MAX_LINE_LEN - 1, MAX_LINE_LEN+1, - handle) != NULL && - strchr(line, '\n') == NULL); - } - - if (strchr( comment, *line ) != NULL) - continue; - else if (strncmp(line, terminator, 2) == 0) { - break; - } - else { - if ( (name_ptr = strtok(line, whitespace)) != NULL && - (seq_ptr = strtok( NULL, whitespace )) != NULL) - got_line = 1; - } - } - } while (! got_line); - - if (! got_line) - fatal_util( "The alignment file appears to have no valid lines in Stockholm format\n"); - - while (got_line) { - - if (numblocks == 0) { - /* if this is the first block, set up the memory for the sequences themselves */ - if (thisseq == 0) { - aln->seqs = (struct Sequence **) malloc_util ( sizeof( struct Sequence *)); - aln->numseqs = 1; - } - else { - aln->numseqs++; - aln->seqs = (struct Sequence **) realloc_util( aln->seqs, aln->numseqs * sizeof( struct Sequence *)); - } - - aln->seqs[thisseq] = empty_Sequence(); - aln->seqs[thisseq]->length = 0; - aln->seqs[thisseq]->name = (char *) malloc_util( (strlen( name_ptr ) + 1) * sizeof(char)); - strcpy( aln->seqs[thisseq]->name, name_ptr ); - - /* get rid of whitespace at end of line */ - for ( last_idx = strlen(seq_ptr) - 1; strchr(whitespace, seq_ptr[last_idx]) != NULL; last_idx--); - aln->seqs[thisseq]->seq = (char *) malloc_util( (last_idx + 1) * sizeof (char ) ); - } - else { - if (strcmp(aln->seqs[thisseq]->name, name_ptr) != 0) { - warning_util("Your seq names are inconsistent across blocks. Using the names in the first block"); - } - - /* The following accounts for the fact that there may be whitepasce at the end of the line */ - for ( last_idx = strlen(seq_ptr) - 1; strchr(whitespace, seq_ptr[last_idx]) != NULL; last_idx--); - - aln->seqs[thisseq]->seq = (char *) realloc_util(aln->seqs[thisseq]->seq, - (aln->seqs[thisseq]->length + last_idx + 1) * sizeof(char)); - - } - - /* and finally, copy the string across */ - for( j=0; j <= last_idx; j++, aln->seqs[thisseq]->length++) - aln->seqs[thisseq]->seq[aln->seqs[thisseq]->length] = seq_ptr[j]; - - /* read the next line. If we come across one or more blank lines while - we do so, then assume that we are starting a new block */ - - got_line = saw_blank_line = 0; - do { - if (fgets(line, lineAllocSize, handle) != NULL) { - if (strchr(line, '\n') == NULL) { /* did not read whole line! */ - do { - lineAllocSize += MAX_LINE_LEN; - line = (char *) realloc_util( line, lineAllocSize * sizeof(char) ); - } while (fgets(line + lineAllocSize - MAX_LINE_LEN-1, MAX_LINE_LEN+1, - handle) != NULL && - strchr(line, '\n') == NULL); - } - - if (strchr( comment, *line ) != NULL) - continue; - else if (strncmp(line, terminator, 2) == 0) { - break; - } - else { - if ( (name_ptr = strtok(line, whitespace)) == NULL) { - saw_blank_line = 1; - } - else if ( (seq_ptr = strtok(NULL, whitespace)) != NULL) - got_line = 1; - } - } - else - break; - - } while (! got_line ); - - - if (got_line) { - if (saw_blank_line) { - numblocks++; - thisseq = 0; - } - else { - thisseq++; - } - } - } - - free_util(line); - - /* just before we return, check the alignment */ - for(i=0; i < aln->numseqs; i++) { - if (i==0) - aln->length = aln->seqs[i]->length; - else if (aln->length != aln->seqs[i]->length) { - fatal_util( "Your alignment segments were of different sizes!\n"); - } - } - - return aln; -} - diff --git a/externalTools/quicktree_1.1/src/aln2dist.c b/externalTools/quicktree_1.1/src/aln2dist.c deleted file mode 100644 index e5e8dc4..0000000 --- a/externalTools/quicktree_1.1/src/aln2dist.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Last edited: Aug 25 15:29 1999 (klh) */ -/*********************************************************************** - ** FILE: aln2dist.c - ** NOTES: - ** This program constructs a DistanceMatrix from the given - ** multiple sequence alignment - ***********************************************************************/ - -#include "aln2dist.h" - - -/********************* command-line options * ************************/ - -static char usage[] = "\ -Usage: treemaker [-options] \n\ -Options are:\n\ --kimura : Use the kimura translation for pairwise distances\n\ -"; - -static struct Option options[] = { - { "-kimura", NO_ARGS }, - { "-h", NO_ARGS } -}; - -static unsigned int use_kimura = 0; - - -/********************************************************************* - FUNCTION: produce_matrix_aln2dist - DESCRIPTION: - Given a fule handle to an alignment, creates and prints a neighbour - joining phlogenetic tree for the sequences in the alignment - RETURNS: void - ARGS: - void - NOTES: - *********************************************************************/ - -void maketree_treemaker( FILE *input ) { - struct Alignment *aln; - struct DistanceMatrix *mat; - - /******* METHOD *************************************** - 1. Read the alignment. - 2. Use it to create the distance matrix - 3. Print the matrix in phylip format - *******************************************************/ - - if ( ( aln = read_MUL_Alignment( input )) == NULL) - fatal_util( "Parse error in alignment file: Must be in MUL format"); - fclose( input ); - - mat = empty_DistanceMatrix( aln->numseqs ); - calc_DistanceMatrix( mat, aln, FALSE, use_kimura ); - write_phylip_DistanceMatrix( stdout, mat, aln ); - - /* before freeing the cluster, nullify the members field, which is actually - pointing to part of the alignment */ - - mat = free_DistanceMatrix( mat ); - aln = free_Alignment( aln ); - - exit(0); -} - - - - - -/********************************************************************* - MAIN - *********************************************************************/ - -void main (int argc, char *argv[]) { - - FILE *input; - char *fname; - - char *optname; /* name of option found by getoption */ - char *optarg; /* argument found by getoption */ - unsigned int optindex; /* index in argv[] */ - - - while (get_option( argc, - argv, - options, - sizeof(options) / sizeof( struct Option ), - usage, - &optindex, - &optname, - &optarg )){ - if (strcmp(optname, "-kimura") == 0) use_kimura = 1; - else if (strcmp(optname, "-h") == 0) { - fprintf( stderr, "%s", usage ); - exit(0); - } - } - - if (argc - optindex != 1) { - fatal_util("Fatal error: Incorrect number of arguements.\n%s\n", usage ); - } - - fname = argv[optindex]; - - if ((input = fopen( fname, "r" )) == NULL) - fatal_util( "Could not open file %s for reading", fname ); - - maketree_treemaker( input ); -} diff --git a/externalTools/quicktree_1.1/src/aln2tree.c b/externalTools/quicktree_1.1/src/aln2tree.c deleted file mode 100644 index 82c2410..0000000 --- a/externalTools/quicktree_1.1/src/aln2tree.c +++ /dev/null @@ -1,147 +0,0 @@ -/* Last edited: Jun 21 11:57 2001 (klh) */ -/*********************************************************************** - ** FILE: aln2tree.c - ** NOTES: - ** This program constructs a phylogenetic tree from a given align- - ** ment file. The process comprises of two phases: - ** 1. Construction of a distance matrix. Here, the optional -k - ** is used to determine whether Kimura's tranlation is used to - ** hopefully obtain more accurate distance - ** 2. The construction of the tree. It is printed in New-Hampshire - ** format to standard output - ***********************************************************************/ - -#include "aln2tree.h" - - -/********************* command-line options * ************************/ - -static char usage[] = "\ -Usage: treemaker [-options] \n\ -Options are:\n\ --kimura : Use the kimura translation for pairwise distances\n\ --boot : Calcuate bootstrap values with n iterations\n\ -"; - -static struct Option options[] = { - { "-kimura", NO_ARGS }, - { "-boot", INT_ARG }, - { "-h", NO_ARGS } -}; - -static unsigned int use_kimura = 0; -static unsigned int calc_bootstraps = 0; - - -/********************************************************************* - FUNCTION: maketree_treemaker - DESCRIPTION: - Given a fule handle to an alignment, creates and prints a neighbour - joining phlogenetic tree for the sequences in the alignment - RETURNS: void - ARGS: - void - NOTES: - *********************************************************************/ - -void maketree_treemaker( FILE *input ) { - struct Alignment *aln, *cons_aln; - struct Tree *myTree, *testTree; - struct ClusterGroup *group; - unsigned int trial; - - /******* METHOD *************************************** - 1. Read the alignment. - 2. Create a ClusterGroup from the alignment, - merging all identical sequences - 3. Grab the alignment of consensi from the - ClusterGroup for later bootstrapping - 4. Build the tree from the cluster group - 5. Bootstrap if required - 6. Print the tree - *******************************************************/ - - if ( ( aln = read_Stockholm_Alignment( input )) == NULL) - fatal_util( "Parse error in alignment file: Must be in MUL format"); - fclose( input ); - - /* - write_MUL_Alignment(stderr, aln); - exit(0); - */ - - group = alignment_to_ClusterGroup( aln, TRUE ); - aln = free_Alignment( aln ); - cons_aln = consensus_aln_from_ClusterGroup( group ); - group->matrix = empty_DistanceMatrix( group->numclusters ); - calc_DistanceMatrix( group->matrix, cons_aln, FALSE, use_kimura ); - - myTree = neighbour_joining_buildtree( group, calc_bootstraps ); - - if (calc_bootstraps) { - for (trial=0; trial < calc_bootstraps; trial++) { - calc_DistanceMatrix( group->matrix, cons_aln, TRUE, use_kimura ); - - testTree = neighbour_joining_buildtree( group, calc_bootstraps ); - update_bootstraps_Tree( myTree, testTree, group->numclusters ); - testTree = free_Tree( testTree ); - } - scale_bootstraps_Tree( myTree, calc_bootstraps ); - write_newhampshire_Tree( stdout, myTree, TRUE ); - } - else { - write_newhampshire_Tree( stdout, myTree, FALSE ); - } - - cons_aln = free_Alignment( cons_aln ); - group = free_ClusterGroup( group ); - myTree = free_Tree( myTree ); - - exit(0); -} - - - - - -/********************************************************************* - MAIN - *********************************************************************/ - -void main (int argc, char *argv[]) { - - FILE *input; - char *fname; - - char *optname; /* name of option found by getoption */ - char *optarg; /* argument found by getoption */ - unsigned int optindex; /* index in argv[] */ - - - while (get_option( argc, - argv, - options, - sizeof(options) / sizeof( struct Option ), - usage, - &optindex, - &optname, - &optarg )){ - if (strcmp(optname, "-kimura") == 0) use_kimura = 1; - else if (strcmp(optname, "-boot") == 0) calc_bootstraps = atoi( optarg ); - else if (strcmp(optname, "-h") == 0) { - fprintf( stderr, "%s", usage ); - exit(0); - } - } - - if (argc - optindex != 1) { - fatal_util("Fatal error: Incorrect number of arguements.\n%s\n", usage ); - } - - fname = argv[optindex]; - - if ((input = fopen( fname, "r" )) == NULL) - fatal_util( "Could not open file %s for reading", fname ); - - maketree_treemaker( input ); -} diff --git a/externalTools/quicktree_1.1/src/buildtree.c b/externalTools/quicktree_1.1/src/buildtree.c deleted file mode 100644 index 591a747..0000000 --- a/externalTools/quicktree_1.1/src/buildtree.c +++ /dev/null @@ -1,750 +0,0 @@ -/* Last edited: Mar 18 11:52 2002 (klh) */ -/********************************************************************** - ** FILE: buildtree.c - ** NOTES: - ** Contains functions for building trees from distance matrices - ** (and vice versa) - **********************************************************************/ - -#include "buildtree.h" - -/********************************************************************** - FUNCTION: export_distances_buildtree - DESCRIPTION: - Returns the distance matrix induced from the given tree, i.e. by summing - the branch paths between two nodes to obtain their distance - ARGS: - A Tree - A DistanceMatrix - RETURNS: - NOTES: - This function does not create the memory for the distance matrix, it - merely fills in the given matrix - **********************************************************************/ -void export_distances_buildtree( struct Tree *thetree, - struct DistanceMatrix *mat) { - - struct Tnode *root; - unsigned int *considered; - - /* first, create the imaginary node that sits between the three nodes - of the unrooted tree */ - - root = new_interior_Tnode( thetree->numnodes ); - - /* now set up the connections */ - - root->parent = thetree->child[0]; - root->left = thetree->child[1]; - root->right = thetree->child[2]; - root->left->parent = root; - root->right->parent = root; - root->parent->parent = root; /* This one seems odd but we need it */ - root->distance = root->parent->distance; - - /* A boolean array to store which nodes have been considered */ - - considered = (unsigned int *) - malloc_util( (thetree->numnodes + 1) * sizeof( unsigned int ) ); - - leaf_find_buildtree( root->parent, mat, considered, thetree->numnodes + 1); - leaf_find_buildtree( root->left, mat, considered, thetree->numnodes + 1); - leaf_find_buildtree( root->right, mat, considered, thetree->numnodes + 1); - - - considered = free_util( considered ); - - /* When freeing the temporary root we have created, we must nullify - the parent and children. We don't want to cause a cascading delete - of the tree */ - - root->parent = NULL; - root->left = NULL; - root->right = NULL; - root = free_Tnode( root ); - -} - - - - -/********************************************************************** - FUNCTION: find_path_buildtree - DESCRIPTION: - Given a leaf node, recursively calculates the branch-length distance - from the node to all other leaves in the tree, and places it in the - appropriate part of the DistanceMatrix - ARGS: - unsigned int (the number of the node from which we are finding all distances) - Tnode (the current node under consideration) - DistanceMatrix - Boolean array (to store which nodes have already been considered) - unsigned int (the size of this boolean array) - RETURNS: - NOTES: - **********************************************************************/ -void find_path_buildtree( unsigned int home, - struct Tnode *node, - struct DistanceMatrix *mat, - Distance dist, - unsigned int *considered) { - - if (node->left == NULL && node->right == NULL) { - if (home < node->nodenumber) { - mat->data[node->nodenumber][home] = dist; - } - else { - mat->data[home][node->nodenumber] = dist; - } - } - else { - /* we have an internal node */ - considered[node->nodenumber] = 1; - - if (node->left != NULL) { - if (! considered[node->left->nodenumber]) { - find_path_buildtree( home, - node->left, - mat, - dist + node->left->distance, - considered ); - } - } - if (node->right != NULL) { - if (! considered[node->right->nodenumber]) { - find_path_buildtree( home, - node->right, - mat, - dist + node->right->distance, - considered ); - } - } - if (node->parent != NULL) { - if (! considered[node->parent->nodenumber]) { - find_path_buildtree( home, - node->parent, - mat, - dist + node->distance, - considered ); - } - } - } - -} - - -/********************************************************************** - FUNCTION: leaf_find_buildtree - DESCRIPTION: - Finds the leaf nodes descended from the given interior node, and - calculates the distance from these nodes to all other nodes, by - way of another function call - ARGS: - Tnode - DistanceMatrix - Boolean array (to store which nodes have already been considered) - RETURNS: - NOTES: - **********************************************************************/ -void leaf_find_buildtree( struct Tnode *node, - struct DistanceMatrix *mat, - unsigned int *considered, - unsigned int size) { - - unsigned int i; - - if (node->left != NULL || node->right != NULL) { - if (node->left != NULL) - leaf_find_buildtree( node->left, mat, considered, size ); - if (node->right != NULL) - leaf_find_buildtree( node->right, mat, considered, size ); - } - else { - - mat->data[node->nodenumber][node->nodenumber] = 0.0; - for(i=0; i < size; i++) considered[i] = 0; - considered[node->nodenumber] = 1; - find_path_buildtree( node->nodenumber, - node->parent, - mat, - node->distance, - considered); - } - -} - - - - -/********************************************************************** - FUNCTION: neighbour_joining_buildtree - DESCRIPTION: - Returns a phylogenetic tree of the sequences in the - given alignment, using Saitou and Nei's neighbour-joining - algorithm - ARGS: - A ClusterGroup pointer (cluster.h) - Boolean, for whether to calc information needed for later bootstrapping - RETURNS: - A Tree (trees.h) - NOTES: The function allocates all the memory necessary for the tree. - The caller should call free_tree (tree.h) to free this memory when - the tree is no longer needed - **********************************************************************/ -struct Tree *neighbour_joining_buildtree( struct ClusterGroup *group, - unsigned int bootstrap) { - unsigned int numseqs, i, j; /*** The current pair of nodes ***/ - unsigned int k, m, nodecount; /*** loop counters ***/ - unsigned int row, column; /*** matrix indices ***/ - unsigned int mini = 0, minj = 0; /*** neighbouring nodes ***/ - unsigned int nextfreenode; /*** incremental labels to nodes ***/ - unsigned int leftovers[3]; /*** three remaining nodes ***/ - struct DistanceMatrix *mat; - struct Tree *theTree; - struct Tnode **nodes; /*** starts off holding leaves ***/ - struct Tnode *newnode; - double fnumseqs; /*** divisor for sums ***/ - double dmj, dmi, ri, minsofar, dist, dij, dist_i, dist_j, dist_k; - Distance *r; /*** stores the r values ***/ - - - /* METHOD *********************************** - I have implemented the neightbour-joining algorithm as descibed - by Durbin, Eddy, Krogh and Mitchison (1998 pp 171-172); see the - text for reasoning behind variable names. I have inserted several - changes from the basic algorithm for reasons of efficiency - - To keep track of dead nodes, we use the 'nodes' pointer array. - Whenever we amalgamate nodes, we overwrite one of the entries - with the new node and set the other to NULL. The NULL entries - in the nodes array thus mark the dead nodes; this is important - when updating the distance matrix because we must not add terms - from nodes that are gone. - - Note the complex indexing of the distance matrix, since it is - assumed that it is triangularised at the top-right. Two Ways - around this: - 1. Abstract the indexing into a distancemat method - 2. Assume a square symmetrical matrix - Method one may have performance impact; method two is more viable - but need to be much more cafeful with the updating of the matrix - at the end of each iteration - - I have also used a modified version of Bill Bruno's idea to attempt - to eliminate negative branch lengths in generated trees. - - ********************************************/ - - - - /******* intialisation ********************/ - - nodes = (struct Tnode **) malloc_util( group->numclusters * sizeof(struct Tnode *)); - for( i=0; i < group->numclusters; i++) { - nodes[i] = new_leaf_Tnode( i, clone_Cluster( group->clusters[i]) ); - } - - mat = group->matrix; - numseqs = nextfreenode = mat->size; - - theTree = empty_Tree(); - - fnumseqs = (double) numseqs; - - - if (numseqs > 2) { - - r = (Distance *) malloc_util( numseqs * sizeof( Distance ) ); - /* Calculate r[i] for all i */ - for( i=0; i < numseqs; i++ ) { - ri = 0.0; - for (k=0; k < numseqs; k++) { - if (k > i) ri += mat->data[k][i]; - else ri += mat->data[i][k]; - } - r[i] = ri / (fnumseqs - 2.0); - } - - - /******* main loop ************************/ - - for (nodecount=0; nodecount < numseqs-3; nodecount++) { - - /* do the intialisation necessary for each iteration here */ - - minsofar = FLT_MAX; /* from float.h */ - - /******* for each pair of matrix entries *********************/ - - for( i=0; i < numseqs; i++ ) { - if (nodes[i] == NULL) continue; - for( j=0; j < i; j++ ) { - if (nodes[j] == NULL) continue; - - dist = mat->data[i][j] - (r[i] + r[j]); - if (dist < minsofar) { - minsofar = dist; - mini = i; - minj = j; - } - } - } - - /* printf("i = %d, j = %d\n", mini, minj); */ - - /* we have the neighbouring i, j; lets calc distances and make the new node */ - - dij = mat->data[mini][minj]; - dist_i = (dij + r[mini] - r[minj]) * 0.5; - dist_j = dij - dist_i; - - /* Adjustment to allow for negative branch lengths */ - if (dist_i < 0.0) { - dist_i = 0.0; - dist_j = dij; - if (dist_j < 0.0) - dist_j = 0.0; - } - else if (dist_j < 0.0) { - dist_j = 0.0; - dist_i = dij; - if (dist_i < 0.0) - dist_i = 0.0; - } - - nodes[mini]->distance = dist_i; - /* printf("DistanceI = %f\n", nodes[mini]->distance); */ - - nodes[minj]->distance = dist_j; - /* printf("DistanceJ = %f\n", nodes[minj]->distance); */ - - newnode = new_interior_Tnode( nextfreenode++ ); - newnode->left = nodes[mini]; - newnode->right = nodes[minj]; - nodes[mini]->parent = newnode; - nodes[minj]->parent = newnode; - nodes[mini] = newnode; - nodes[minj] = NULL; - if (bootstrap) { - /* we need to create and load the 'bit' field of child ids */ - - newnode->child_ids = (unsigned int *) - malloc_util( group->numclusters * sizeof( unsigned int ) ); - for (m=0; m < group->numclusters; m++) { - if ( (newnode->left->child_ids != NULL && newnode->left->child_ids[m]) || - (newnode->right->child_ids != NULL && newnode->right->child_ids[m]) || - (newnode->left->nodenumber == m || - newnode->right->nodenumber == m || - newnode->nodenumber == m)) { - newnode->child_ids[m] = 1; - } - else { - newnode->child_ids[m] = 0; - } - } - } - - /* now update the distance matrix; This needs hackery to make sure that the - indexing is correct */ - - r[mini] = 0.0; /* This is the only r[i] that requires wholesale changes */ - for( m=0; m < numseqs; m++ ) { - if (nodes[m] == NULL) continue; - - if (m != mini) { - - if (m > minj) dmj = mat->data[m][minj]; - else dmj = mat->data[minj][m]; - - if (m > mini) { - row = m; - column = mini; - } - else { - row = mini; - column = m; - } - dmi = mat->data[row][column]; - - /* we can actually adjust r[m] here, by using the form: - rm = ((rm * numseqs) - dmi - dmj + dmk) / (numseqs-1) - */ - - /* Note: in Bill Bruno's method for negative branch elimination, then if either - dist_i is positive and dist_j is 0, or dist_i is zero and dist_j is positive - (after adjustment) then the matrix entry is formed from the distance to the - node in question (m) to the node with the zero branch length (whichever it was). - I think my code already has the same effect; this is certainly true if dij is - equal to dist_i + dist_j, which it should have been fixed to - */ - - mat->data[row][column] = (dmi + dmj - dij) * 0.5; - r[m] = ((r[m] * (fnumseqs - 2.0)) - dmi - dmj + mat->data[row][column]) / (fnumseqs - 3.0); - r[mini] += mat->data[row][column]; - } - } - - fnumseqs -= 1.0; - r[mini] /= fnumseqs - 2.0; - - } - /******* end of main loop ******************/ - - - /* Now there are just 3 nodes left. Need to locate those three nodes */ - /* The following looks dangerous, because we only have room for three nodes in the tree; - However, all nodes except three should be NULL, or else something is seriously wrong */ - - for(k=0, m=0; k < numseqs; k++) { - if (nodes[k] != NULL) { - theTree->child[m] = nodes[k]; - leftovers[m++] = k; - nodes[k] = NULL; /* so that the nodes are not released when input is */ - } - } - - - /* Now to get rid of those negative branch lengths (see you in ~70 lines....) */ - - dist_i = theTree->child[0]->distance = - (mat->data[leftovers[1]][leftovers[0]] + - mat->data[leftovers[2]][leftovers[0]] - - mat->data[leftovers[2]][leftovers[1]]) * 0.5; - dist_j = theTree->child[1]->distance = mat->data[leftovers[1]][leftovers[0]] - theTree->child[0]->distance; - dist_k = theTree->child[2]->distance = mat->data[leftovers[2]][leftovers[0]] - theTree->child[0]->distance; - - - if (dist_i < 0.0) { - dist_i = 0.0; - dist_j = mat->data[leftovers[1]][leftovers[0]]; - dist_k = mat->data[leftovers[2]][leftovers[0]]; - if (dist_j < 0.0) { - dist_j = 0.0; - dist_k = ( mat->data[leftovers[2]][leftovers[0]] + - mat->data[leftovers[2]][leftovers[1]] ) * 0.5; - if (dist_k < 0.0) - dist_k = 0.0; - } - else if (dist_k < 0.0) { - dist_k = 0.0; - dist_j = - (mat->data[leftovers[1]][leftovers[0]] + - mat->data[leftovers[2]][leftovers[1]] ) * 0.5; - if (dist_j < 0.0) - dist_j = 0.0; - } - } - else if (dist_j < 0.0) { - dist_j = 0.0; - dist_i = mat->data[leftovers[1]][leftovers[0]]; - dist_k = mat->data[leftovers[2]][leftovers[1]]; - if (dist_i < 0.0) { - dist_i = 0.0; - dist_k = ( mat->data[leftovers[2]][leftovers[0]] + - mat->data[leftovers[2]][leftovers[1]] ) * 0.5; - if (dist_k < 0.0) - dist_k = 0.0; - } - else if (dist_k < 0.0) { - dist_k = 0.0; - dist_i = - (mat->data[leftovers[1]][leftovers[0]] + - mat->data[leftovers[2]][leftovers[0]] ) * 0.5; - if (dist_i < 0.0) - dist_i = 0.0; - } - } - else if (dist_k < 0.0) { - dist_k = 0.0; - dist_i = mat->data[leftovers[2]][leftovers[0]]; - dist_j = mat->data[leftovers[2]][leftovers[1]]; - if (dist_i < 0.0) { - dist_i = 0.0; - dist_j = ( mat->data[leftovers[1]][leftovers[0]] + - mat->data[leftovers[2]][leftovers[1]] ) * 0.5; - if (dist_j < 0.0) - dist_j = 0.0; - } - else if (dist_j < 0.0) { - dist_j = 0.0; - dist_i = - (mat->data[leftovers[1]][leftovers[0]] + - mat->data[leftovers[2]][leftovers[0]] ) * 0.5; - if (dist_i < 0.0) - dist_i = 0.0; - } - } - - - - theTree->child[0]->distance = dist_i; - theTree->child[1]->distance = dist_j; - theTree->child[2]->distance = dist_k; - - - r = free_util( r ); - } - else { - /* deal with the trivial case of less than three leaves */ - - for( i=0; i < numseqs; i++ ) { - theTree->child[i] = nodes[i]; - nodes[i] = NULL; - } - - if (numseqs == 2) { - theTree->child[0]->distance = mat->data[1][0] * 0.5; - theTree->child[1]->distance = mat->data[1][0] * 0.5; - } - } - - /* nextfreenode records how many calls to new_Tnode_tree we made; therefore, at this stage, it - holds the total number of nodes (including leaves) in the tree */ - theTree->numnodes = nextfreenode; - - nodes = free_util( nodes ); - - /* The caller of the function should free the tree when finished with it */ - - return theTree; -} - - - -/********************************************************************** - FUNCTION: UPGMA_buildtree - DESCRIPTION: - Returns a phylogenetic tree of the sequences in the - given alignment, using the Unweighted Pair-Group method based on - Arithmentic Averages (UPGMA) - ARGS: - A ClusterGroup pointer (cluster.h) - A boolean,for whether to record information needed later for bootstrapping - RETURNS: - struct Tree (trees.h) - NOTES: The function allocates all the memory necessary for the tree. - The caller should call free_Tnode (tree.h) to free this memory when - the tree is no longer needed - - This algorithm produces a rooted tree; hence the returned Tree - will have the root in child[0]; child[1] and child[2] (used to - represent the trichotomy of unrooted trees) will be NULL - **********************************************************************/ -struct Tree *UPGMA_buildtree(struct ClusterGroup *group, - unsigned int bootstrap) { - - unsigned int numseqs, i, j; /*** The current pair of nodes ***/ - unsigned int m, nodecount; /*** loop counters ***/ - unsigned int row, column; /*** matrix indices ***/ - unsigned int mini = 0, minj = 0; /*** neighbouring nodes ***/ - unsigned int nextfreenode; /*** incremental labels to nodes ***/ - unsigned int *subtreesizes; - Distance *heights; - double minsofar, newnodeheight, dmi, dmj; - - struct DistanceMatrix *mat = NULL; - struct Tree *theTree = NULL; - struct Tnode **nodes = NULL; /*** starts off holding leaves ***/ - struct Tnode *newnode = NULL; - - /* METHOD *********************************** - I have implemented the UPGMA algorithm as presented - by Durbin, Eddy, Krogh and Mitchison (1998 pp 171-172). - - To keep track of merged nodes, we use the 'nodes' pointer array. - Whenever we amalgamate nodes, we overwrite one of the entries - with the new node and set the other to NULL. The NULL entries - in the nodes array thus mark the dead nodes; this is important - when updating the distance matrix because we must not add terms - from nodes that are gone. - - Note the complex indexing of the distance matrix, since it is - assumed that it is triangularised at the top-right. Two Ways - around this: - 1. Abstract the indexing into a distancemat method - 2. Assume a square symmetrical matrix - Method one may have performance impact; method two is more viable - but need to be much more cafeful with the updating of the matrix - at the end of each iteration - - ********************************************/ - - - - /******* intialisation ********************/ - - nodes = (struct Tnode **) malloc_util( group->numclusters * sizeof(struct Tnode *)); - heights = (Distance *) malloc_util( group->numclusters * sizeof(Distance)); - subtreesizes = (unsigned int *) malloc_util( group->numclusters * sizeof(unsigned int)); - for( i=0; i < group->numclusters; i++) { - nodes[i] = new_leaf_Tnode( i, group->clusters[i] ); - /* clusters[i] in group has conceptually moved into the Tnode, so... */ - group->clusters[i] = NULL; - - heights[i] = 0.0; - subtreesizes[i] = 1; - } - - mat = group->matrix; - numseqs = nextfreenode = mat->size; - - theTree = empty_Tree(); - - /******* main loop ************************/ - - if (numseqs == 1) - newnode = nodes[0]; - else { - /*** new code ***/ - Distance *min_of_row = (Distance *) malloc_util( numseqs * sizeof( Distance )); - int *min_of_row_idx = (int *) malloc_util( numseqs * sizeof( int )); - - /* calculate in advance the minimum column for each row */ - for(i=1; i < numseqs; i++) { - min_of_row[i] = FLT_MAX; - min_of_row_idx[i] = -1; - - for(j=0; j < i; j++) { - - if (mat->data[i][j] < min_of_row[i]) { - min_of_row[i] = mat->data[i][j]; - min_of_row_idx[i] = j; - } - } - } - - - for (nodecount=0; nodecount < numseqs-1; nodecount++) { - - /* do the intialisation necessary for each iteration here */ - - minsofar = FLT_MAX; /* from float.h */ - - for( i=1; i < numseqs; i++) { - if (nodes[i] == NULL) continue; - if ( min_of_row[i] < minsofar ) { - minsofar = min_of_row[i]; - mini = i; - minj = min_of_row_idx[i]; - } - } - - /* we have the neighbouring i, j; lets calc distances and make the new node */ - - newnodeheight = mat->data[mini][minj] * 0.5; - nodes[mini]->distance = newnodeheight - heights[mini]; - nodes[minj]->distance = newnodeheight - heights[minj]; - - newnode = new_interior_Tnode( nextfreenode++ ); - newnode->left = nodes[mini]; - newnode->right = nodes[minj]; - nodes[mini]->parent = newnode; - nodes[minj]->parent = newnode; - if (bootstrap) { - /* we need to create and load the 'bit' field of child ids */ - - newnode->child_ids = (unsigned int *) - malloc_util( group->numclusters * sizeof( unsigned int ) ); - for (i=0; i < group->numclusters; i++) { - if ( (newnode->left->child_ids != NULL && - (newnode->left->child_ids[i] || newnode->left->child_ids[i])) || - (newnode->right->child_ids != NULL && - (newnode->right->child_ids[i] || newnode->right->child_ids[i])) || - (newnode->left->nodenumber == i || - newnode->right->nodenumber == i || - newnode->nodenumber == i)) { - newnode->child_ids[i] = 1; - } - else { - newnode->child_ids[i] = 0; - } - } - } - - /* now update the distance matrix; This needs hackery to make sure that the - indexing is correct */ - - min_of_row[mini] = FLT_MAX; - min_of_row_idx[mini] = -1; - - for( m=0; m < numseqs; m++ ) { - if (nodes[m] == NULL) continue; - - /* dmini,m*|Ci| + dminj,m*|Cj| - dmini,m = --------------------------- - |Ci| + |Cj| - */ - - if (m > minj) dmj = mat->data[m][minj]; - else dmj = mat->data[minj][m]; - - if (m > mini) { - row = m; - column = mini; - } - else { - row = mini; - column = m; - } - - dmi = mat->data[row][column]; - - mat->data[row][column] = - (( dmi * subtreesizes[mini])+( dmj * subtreesizes[minj])) / - (subtreesizes[mini] + subtreesizes[minj]); - - if (mat->data[row][column] < min_of_row[row] - && nodes[column] != NULL - && column != minj - && row != column) { - min_of_row[row] = mat->data[row][column]; - min_of_row_idx[row] = column; - } - - /* node minj is being nullified, so any row that points to it - is min should be updated */ - if (m != mini && m != 0) { - if (min_of_row_idx[m] == minj || min_of_row_idx[m] == mini) { - min_of_row[m] = FLT_MAX; - min_of_row_idx[m] = -1; - for(j=0; j < m; j++) { - if (nodes[j] == NULL || j == minj) continue; - if (mat->data[m][j] < min_of_row[m]) { - min_of_row[m] = mat->data[m][j]; - min_of_row_idx[m] = j; - } - } - } - } - } - - heights[mini] = newnodeheight; - subtreesizes[mini] = subtreesizes[mini] + subtreesizes[minj] + 1; - - nodes[mini] = newnode; - nodes[minj] = NULL; - - } - - free_util( min_of_row ); - free_util( min_of_row_idx ); - - } - /******* end of main loop ******************/ - - - theTree->child[0] = newnode; - - /* nextfreenode records how many calls to new_Tnode_tree we made; therefore, at this stage, it - holds the total number of nodes (including leaves) in the tree */ - - theTree->numnodes = nextfreenode; - nodes = free_util( nodes ); - heights = free_util( heights ); - subtreesizes = free_util( subtreesizes ); - - /* The caller of the function should free the tree when finished with it */ - - return theTree; - -} diff --git a/externalTools/quicktree_1.1/src/cluster.c b/externalTools/quicktree_1.1/src/cluster.c deleted file mode 100644 index 868b741..0000000 --- a/externalTools/quicktree_1.1/src/cluster.c +++ /dev/null @@ -1,357 +0,0 @@ -/* Last edited: Feb 1 18:18 2002 (klh) */ -/********************************************************************** - ** FILE: cluster.c - ** NOTES: - ** A DistanceMatrix should always be part of a Cluster - ** It makes no sense to have a set of pairwise distances without the - ** associated sequences (even if we just store their names) - **********************************************************************/ - -#include "cluster.h" - - - -/********************************************************************* - FUNCTION: alignment_to_ClusterGroup - DESCRIPTION: - This function returns a ClusterGroup, given an Alignment. - if the secind arg is true, In doing indentical sequences in the - alignment are merged. If bootstrapping is required, the consensus - alignment can be extracted from the ClusterGroup using - get_consensus_from_ClusterGroup - RETURNS: struct ClusterGroup - ARGS: - 1. A source Alignment pointer - 2. A boolean specifying whether duplicate sequences should be - merged. - NOTES: -*********************************************************************/ -struct ClusterGroup *alignment_to_ClusterGroup( struct Alignment *aln, - unsigned int remove_duplicates) { - unsigned int i, j, numclusters; - struct ClusterGroup *group; - struct Cluster **newclusts; - - group = empty_ClusterGroup(); - - /* Need to create a cluster for every sequence in the given cluster */ - - newclusts = (struct Cluster **) malloc_util( aln->numseqs * sizeof( struct Cluster *) ); - - - for( i=0; i < aln->numseqs; i++) { - newclusts[i] = single_Sequence_Cluster( clone_Sequence(aln->seqs[i])); - } - numclusters = aln->numseqs; - - if (remove_duplicates) { - for( i=0; i < aln->numseqs; i++) { - if (newclusts[i] == NULL) continue; - for( j=i+1; j < aln->numseqs; j++) { - if (newclusts[j] == NULL) continue; - - if (strncmp( aln->seqs[i]->seq, aln->seqs[j]->seq, aln->length) == 0) { - /* these two clusters contain the same sequence, so we can merge them */ - newclusts[j] = merge_Cluster( newclusts[i], newclusts[j] ); - numclusters--; - } - } - } - } - - - /* newclusts will now be a sparse array containing clusters of - identical sequences */ - - group->numclusters = numclusters; - group->clusters = (struct Cluster **) malloc_util( numclusters * sizeof( struct Cluster *) ); - for(i=0, j=0; i < aln->numseqs; i++) { - if (newclusts[i] != NULL) { - group->clusters[j++] = newclusts[i]; - } - } - - newclusts = free_util( newclusts ); - - return group; -} - - -/********************************************************************* - FUNCTION: clone_Cluster - DESCRIPTION: - This function makes a complete copy of the given Cluster - and returns it - RETURNS: struct Cluster * - ARGS: - struct Cluster * - NOTES: -*********************************************************************/ -struct Cluster *clone_Cluster( struct Cluster *source) { - unsigned int i; - struct Cluster *dest = NULL; - - if (source != NULL) { - dest = empty_Cluster(); - dest->clustersize = source->clustersize; - dest->members = (struct Sequence **) malloc_util( dest->clustersize - * sizeof( struct Sequence * )); - for( i=0; i < source->clustersize; i++) { - dest->members[i] = clone_Sequence( source->members[i] ); - } - dest->consensus = clone_Sequence( source->consensus ); - } - - return dest; -} - - - -/********************************************************************* - FUNCTION: consensus_aln_from_ClusterGroup - DESCRIPTION: - This function creates an alignment by taking the consensus - sequences from each Cluster in the given ClusterGroup - RETURNS: struct ClusterGroup - ARGS: - 1. A source Alignment pointer - 2. A boolean specifying whether duplicate sequences should be - merged. - NOTES: -*********************************************************************/ -struct Alignment *consensus_aln_from_ClusterGroup( struct ClusterGroup *grp) { - unsigned int i; - struct Alignment *cons; - - cons = (struct Alignment *) malloc_util( sizeof( struct Alignment )); - cons->numseqs = grp->numclusters; - cons->seqs = (struct Sequence **) malloc_util( grp->numclusters * sizeof( struct Sequence *)); - - for (i=0; i < grp->numclusters; i++) { - cons->seqs[i] = clone_Sequence( grp->clusters[i]->consensus ); - } - /* All consensus seqs will be aligned, so we can pick any one to get - the alignment width */ - cons->length = cons->seqs[0]->length; - - return cons; -} - - - - - -/********************************************************************* - FUNCTION: empty_Cluster - DESCRIPTION: - This function handles the simple task of allocating the space - for a new Cluster. - RETURNS: struct Cluster * - ARGS: - NOTES: -*********************************************************************/ -struct Cluster *empty_Cluster( void ) { - struct Cluster *newclust; - - newclust = (struct Cluster *) malloc_util( sizeof( struct Cluster )); - newclust->clustersize = 0; - newclust->members = NULL; - newclust->consensus = NULL; - newclust->matrix = NULL; - - return newclust; - -} - - - -/********************************************************************* - FUNCTION: empty_ClusterGroup - DESCRIPTION: - This function handles the simple task of allocating the space - for a new ClusterGroup - RETURNS: struct Cluster * - ARGS: - NOTES: -*********************************************************************/ -struct ClusterGroup *empty_ClusterGroup( void ) { - struct ClusterGroup *group; - - group = (struct ClusterGroup *) malloc_util( sizeof(struct ClusterGroup)); - group->numclusters = 0; - group->clusters = NULL; - group->matrix = NULL; - - return group; -} - - - - -/********************************************************************* - FUNCTION: free_Cluster - DESCRIPTION: - This function releases the memory used by this Cluster and all of its - members - RETURNS: A null pointer - ARGS: - struct Cluster * - NOTES: - In the majority of cases, all sequences in the Cluster come from - an alignment, and if this alignment is subsequently needed (e.g. - for bootstrapping) then then the seqs should not be freed. To - prevent this, the members field should be set to null by the caller - to prevent freeing og the alignment -*********************************************************************/ -void *free_Cluster( struct Cluster *given ) { - unsigned int i; - - if (given != NULL) { - if (given->members != NULL) { - for( i=0; i < given->clustersize; i++) { - given->members[i] = free_Sequence( given->members[i] ); - } - given->members = free_util( given->members ); - } - given->matrix = free_DistanceMatrix( given->matrix ); - given->consensus = free_Sequence( given->consensus ); - given = free_util( given ); - } - return given; -} - - - - -/********************************************************************* - FUNCTION: free_ClusterGroup - DESCRIPTION: - This function releases the memory used by this Cluster and all of its - members - RETURNS: A null pointer - ARGS: - struct Cluster * - NOTES: -*********************************************************************/ -void *free_ClusterGroup( struct ClusterGroup *given ) { - unsigned int i; - - if (given != NULL) { - if (given->clusters != NULL) { - for( i=0; i < given->numclusters; i++ ) { - given->clusters[i] = free_Cluster( given->clusters[i] ); - } - given->clusters = free_util( given->clusters ); - } - given->matrix = free_DistanceMatrix( given->matrix ); - given = free_util( given ); - } - - return given; -} - - - - -/********************************************************************* - FUNCTION: merge_Cluster - DESCRIPTION: - Adds the sequences in second arg to first arg, freeing the second - arg, returning the result of this freeing (hopefully NULL); - RETURNS: The result of freeing the second cluster (NULL if all is well) - ARGS: - Destination Cluster *, - Source Cluster * - NOTES: -*********************************************************************/ -void *merge_Cluster( struct Cluster *dest, struct Cluster *source) { - unsigned int i; - - /* take the sequences in source and add them onto the destination list */ - - dest->members = (struct Sequence **) - realloc_util( dest->members, - (dest->clustersize + source->clustersize) * sizeof(struct Sequence *)); - for ( i=0; i < source->clustersize; i++) { - dest->members[ dest->clustersize++ ] = source->members[i]; - source->members[i] = NULL; - } - - /* Need to update the consensus sequence with respect to the merge. - At this stage, I am only merging identical clusters, so the - consensus sequence is already correct in the destination - */ - - source = free_Cluster( source ); - - return source; -} - - - -/********************************************************************* - FUNCTION: single_Sequence_Cluster - DESCRIPTION: - This function handles the simple task of allocating the space - for a new Cluster with the single given Sequence. - RETURNS: struct Cluster * - ARGS: - A pointer to a Sequence, or NULL for an empty Cluster - NOTES: -*********************************************************************/ - -struct Cluster *single_Sequence_Cluster( struct Sequence *seq) { - struct Cluster *newclust; - - newclust = empty_Cluster(); - - if (seq != NULL) { - newclust->clustersize = 1; - newclust->members = (struct Sequence **) malloc_util( sizeof( struct Sequence *) ); - newclust->members[0] = seq; - newclust->consensus = clone_Sequence( seq ); - /* Note how the consensus sequence will end up with the same name as - the first representative of trhe cluster. This is fine, because - when the consensus is used, it is assumed that it is not a real - sequence so its name is meaningless - */ - } - - return newclust; -} - - - - -/********************************************************************* - FUNCTION: single_Cluster_ClusterGroup - DESCRIPTION: - This function takes the given cluster and very simlpy makes a - single-Cluster ClusterGroup from it - RETURNS: struct ClusterGroup * - ARGS: - A pointer to a Cluster - NOTES: -*********************************************************************/ - -struct ClusterGroup *single_Cluster_ClusterGroup( struct Cluster *clust ) { - struct ClusterGroup *group; - - group = empty_ClusterGroup(); - - if (clust != NULL) { - group->numclusters = 1; - group->clusters = (struct Cluster **) malloc_util( sizeof(struct Cluster *)); - group->clusters[0] = clust; - } - - return group; -} - - - - - - - - diff --git a/externalTools/quicktree_1.1/src/dist2tree.c b/externalTools/quicktree_1.1/src/dist2tree.c deleted file mode 100644 index e5b9091..0000000 --- a/externalTools/quicktree_1.1/src/dist2tree.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Last edited: Aug 25 15:14 1999 (klh) */ -/********************************************************************** - ** FILE: dist2tree.c - ** NOTES: - ** This program can be used to generate neighbour-joining - ** trees given a distance matrix file. - ** The matrix file should be in phylip format; the application was - ** originally coded to compare the efficiency of the writer's - ** implementation of neighbourjoining with that of phylip's - ** 'neighbor' program. The tree is writtento stdout in New Hants - ** format. - **********************************************************************/ - -#include "dist2tree.h" - - -/********************************************************************* - FUNCTION: maketree_neighbourjoin - DESCRIPTION: - Given a file handle to a distance matrix, creates and prints a neighbour - joining phlogenetic tree for the sequences in the alignment - RETURNS: void - ARGS: - A file handle to a distance matrix (in 'phylip' format) - NOTES: - *********************************************************************/ - -void maketree_neighbourjoin( FILE *input ) { - struct DistanceMatrix *mat; - struct Alignment *aln; - struct Tree *myTree; - struct ClusterGroup *group; - - /******* METHOD *************************************** - 1. Read the Cluster (reads in the matrix as a side effect). - 4. Shatter the Cluster into several CLusters, thus - forming a ClusterGroup - 5. Build a tree from the ClusterGroup, and print it - *******************************************************/ - - mat = read_phylip_DistanceMatrix( input, &aln ); - fclose( input ); - - /* Note that the alignment here contains no sequences, just names, - so there is no point in trying to merge identical sequences, hence - the FALSE argument - */ - group = alignment_to_ClusterGroup( aln, FALSE ); - group->matrix = mat; - myTree = neighbour_joining_buildtree( group, FALSE ); - write_newhampshire_Tree( stdout, myTree, FALSE ); - - aln = free_Alignment( aln ); - group = free_ClusterGroup( group ); - myTree = free_Tree( myTree ); - -} - - - -/********************************************************************* - MAIN - *********************************************************************/ - -void main (int argc, char *argv[]) { - - FILE *matrixfile; - - if (argc != 2) - fatal_util( "Usage: neighbourjoin matrixfile (in PHYLIP format)"); - else { - if ((matrixfile = fopen( argv[1], "r" )) == NULL) - fatal_util( "Could not open file %s for reading", argv[1] ); - - maketree_neighbourjoin( matrixfile ); - } -} diff --git a/externalTools/quicktree_1.1/src/distancemat.c b/externalTools/quicktree_1.1/src/distancemat.c deleted file mode 100644 index 9d9f5a1..0000000 --- a/externalTools/quicktree_1.1/src/distancemat.c +++ /dev/null @@ -1,450 +0,0 @@ -/* Last edited: Feb 1 18:15 2002 (klh) */ -/********************************************************************** - ** FILE: distancemat.c - ** NOTES: - ** Functions and types for the manipulation of Distance Matrices - **********************************************************************/ - -#include "distancemat.h" - - -/*********************** static variables *****************************/ - -/* This is a table of estimated PAMs for a range of percentage-differences, - ranging from 75% dissimilarity, going up in 0.1% steps, to 93% - dissimilarity. For percentage dissimilarty outside this range, we either - use Kimura's formula (for < 75) or give an arbitrarily high distance - (for > 93) */ - -static int dayhoff_pams[]={ - 195, /* 75.0% observed d; 195 PAMs estimated = 195% estimated d */ - 196, /* 75.1% observed d; 196 PAMs estimated */ - 197, 198, 199, 200, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, - 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 236, 237, 238, 239, 240, 241, 243, 244, 245, - 246, 248, 249, 250, /* 250 PAMs = 80.3% observed d */ - 252, 253, 254, 255, 257, 258, - 260, 261, 262, 264, 265, 267, 268, 270, 271, 273, - 274, 276, 277, 279, 281, 282, 284, 285, 287, 289, - 291, 292, 294, 296, 298, 299, 301, 303, 305, 307, - 309, 311, 313, 315, 317, 319, 321, 323, 325, 328, - 330, 332, 335, 337, 339, 342, 344, 347, 349, 352, - 354, 357, 360, 362, 365, 368, 371, 374, 377, 380, - 383, 386, 389, 393, 396, 399, 403, 407, 410, 414, - 418, 422, 426, 430, 434, 438, 442, 447, 451, 456, - 461, 466, 471, 476, 482, 487, 493, 498, 504, 511, - 517, 524, 531, 538, 545, 553, 560, 569, 577, 586, - 595, 605, 615, 626, 637, 649, 661, 675, 688, 703, - 719, 736, 754, 775, 796, 819, 845, 874, 907, 945, - /* 92.9% observed; 945 PAMs */ - 988 /* 93.0% observed; 988 PAMs */ -}; - - - - -/********************************************************************* - FUNCTION: calc_DistanceMatrix - DESCRIPTION: - Produces a distance matrix from the given multiple alignment - RETURNS: struct DistanceMatrix - ARGS: - A DistanceMatrix to fill in - A multiple alignment - A boolean indicating whether or not random columns should be used - for purposes of bootstrapping - A boolean indicating whether the Kimura distance adjustment is to - be used or not. - NOTES: - 0. the given DistanceMatrix and Alignment should be of the same order - - 1. The matrix produced is in bottom-left triangular format; don't you - go trying to access that top-right section (I'm warning you...) - - 2. At the moment, the function calculates distance based on sequence - identity, using Kimura's function if that option is raised. - - 3. If use_rand_cols is true, then the matrix is constructed using - random sampling of columns, for the purposes of bootstrapping. At - the moment, the native function 'rand' is used to do this, suitable - seeded by time (by the caller). This may prove unsatisfactory... - - 4. Where no information is available to determine the distance - between two sequences, a value of twice the maximum observed - distance is assigned (inspiration from ISMB99 poster by Huson, - Smith and Warnow). - - *********************************************************************/ - -void calc_DistanceMatrix( struct DistanceMatrix *mat, - struct Alignment *aln, - unsigned int use_rand_cols, - unsigned int use_kimura ) { - - /* this function will take alignment and return a distance matrix */ - /* This gives a clear separation between tree making and distances */ - - unsigned int i, j, k, table_index, num_undefined_distances, mem_increment; - unsigned int *columnlist; - Distance residuecount, distance, max_observed_distance; - Distance **undefined_distances; - - columnlist = (unsigned int *) malloc_util( aln->length * sizeof(unsigned int)); - for (i=0; i < aln->length; i++) { - if (use_rand_cols) { - /* generate random column here */ - columnlist[i] = (unsigned int) rand() % aln->length; - } - else { - columnlist[i] = i; - } - } - - max_observed_distance = 0.0; - mem_increment = 10; - undefined_distances = NULL; - num_undefined_distances = 0; - - for( i=0; i < aln->numseqs; i++) { - mat->data[i][i] = 0.0; - for( j=0; j < i; j++ ) { - residuecount = distance = 0.0; - mat->data[i][j] = 0.0; - - for( k=0; k < aln->length; k++) { - if ( aln->seqs[i]->seq[columnlist[k]] == '.' || - aln->seqs[j]->seq[columnlist[k]] == '.' || - aln->seqs[i]->seq[columnlist[k]] == '-' || - aln->seqs[j]->seq[columnlist[k]] == '-' || - aln->seqs[i]->seq[columnlist[k]] == ' ' || - aln->seqs[j]->seq[columnlist[k]] == ' ') - continue; - - /* neither character is a gap, so proceed */ - residuecount += 1.0; - if ( aln->seqs[i]->seq[columnlist[k]] != aln->seqs[j]->seq[columnlist[k]]) - distance += 1.0; - } - - /* if residue count was zero here, there must have been a gap in every position; - in this case, %identity is undefined so a decision must be made to consider the - sequences 100% identical or 100% different. I go with the standard approach of - assigning twoce the maximum observed distance */ - - if (residuecount > 0) { - distance = distance / residuecount; - } - else { - distance = -1.0; - if (num_undefined_distances % mem_increment == 0) { - if (num_undefined_distances == 0) { - undefined_distances = (Distance **) - malloc_util( sizeof( Distance *) * mem_increment); - } - else { - undefined_distances = (Distance **) - realloc_util( undefined_distances, - (num_undefined_distances + mem_increment) * sizeof(Distance *)); - } - } - undefined_distances[num_undefined_distances++] = &(mat->data[i][j]); - /* distances should be zero, but may be slightly less due to floating point - arithmetic */ - } - - /* Use Kimura's formula to convert percentage dissimilarity to a distance */ - - if (use_kimura) { - if ( distance < 0.75) { - if (distance > 0.0) - distance = - log( 1.0 - distance - (distance * distance * 0.20) ); - } - else { - if (distance > 0.930) { - distance = 10.0; - } - else { - table_index = (int) ((distance*1000.0) - 750.0); - distance = (Distance) dayhoff_pams[ table_index ]; - distance /= 100.0; - } - } - } - if (distance > max_observed_distance) { - max_observed_distance = distance; - } - mat->data[i][j] = distance; - } - } - - /* before we go, lets find those undefined distances and replace them with - twice the maximum observed distance */ - - for (i=0; i < num_undefined_distances; i++ ) { - *undefined_distances[i] = 2 * max_observed_distance; - } - - columnlist = free_util( columnlist ); - if (undefined_distances != NULL) { - undefined_distances = free_util( undefined_distances ); - } -} - - - -/********************************************************************* - FUNCTION: clone_DistanceMatrix - DESCRIPTION: - Produces a brand new DistanceMatrix, identical to the source - RETURNS: struct DistanceMatrix - ARGS: - A source distane matrix - NOTES: - 1. The matrix produced is in bottom-left triangular format; don't you - go trying to access that top-right section (I'm warning you...) - *********************************************************************/ -struct DistanceMatrix *clone_DistanceMatrix( struct DistanceMatrix *source) { - unsigned int i,j; - struct DistanceMatrix *dest; - - if (source != NULL) { - dest = empty_DistanceMatrix( source->size ); - - for( i=0; i < dest->size; i++) { - for( j=0; j <= i; j++ ) { - dest->data[i][j] = source->data[i][j]; - } - } - } - else { - dest = NULL; - } - - return dest; -} - - - -/********************************************************************* - FUNCTION: empty_DistanceMatrix - DESCRIPTION: - Produces an empty distance matrixof the given size, uninitialised - RETURNS: struct DistanceMatrix - ARGS: - The size of the matrix to be created - NOTES: - 1. The matrix produced is in bottom-left triangular format; don't you - go trying to access that top-right section (I'm warning you...) - *********************************************************************/ -struct DistanceMatrix *empty_DistanceMatrix( unsigned int size) { - unsigned int i; - struct DistanceMatrix *mat; - - mat = (struct DistanceMatrix *) malloc_util(sizeof(struct DistanceMatrix)); - mat->size = size; - mat->data = (Distance **) malloc_util( mat->size * sizeof(Distance *) ); - - for( i=0; i < mat->size; i++) - mat->data[i] = (Distance *) malloc_util( (i+1) * sizeof(Distance) ); - - return mat; -} - - - -/********************************************************************* - FUNCTION: free_DistanceMatrix - DESCRIPTION: - Frees the memory for the given distance matrix - RETURNS: - ARGS: - struct DistanceMatrix * - NOTES: - *********************************************************************/ - -void *free_DistanceMatrix( struct DistanceMatrix *mat ) { - int i; - - if ( mat != NULL ) { - if (mat->data != NULL) { - for( i=0; i < mat->size; i++ ) { - if (mat->data[i] != NULL) - mat->data[i] = free_util( mat->data[i] ); - } - mat->data = free_util( mat->data ); - } - mat = free_util( mat ); - } - - return mat; -} - - - - -/********************************************************************** - FUNCTION: index_DistanceMatrix - DESCRIPTION: - indexes the given distance matrix with the given indices, - returning the appropraite distance. - RETURNS: distance (float) - ARGS: - A distance matrix * - row index - column index - NOTES: - This function is necessary to account for the fact that the distance - matrix may be implemented as a symmtrical or triangular matrix. - It therefore abstracts the internals of the distance matrix, at the - cost of a function call for each lookup (is this wise...?) - **********************************************************************/ - -Distance index_DistanceMatrix( struct DistanceMatrix *mat, - unsigned int i, - unsigned int j) { - if (i > j) - return mat->data[i][j]; - else - return mat->data[j][i]; -} - - -/********************************************************************* - FUNCTION: print_DistanceMatrix - DESCRIPTION: - Prints the given distance matrix. - RETURNS: - ARGS: - struct DistanceMatrix * - NOTES: - A DistanceMatrix does not exist in isolation in practice but as - part of a Cluster (this is to maintain the tight coupling between - the matrix and the sequences for which it is expressing the distances). - Therefore, to read or write a useful distance - matrix (for compatibility with the phylip package for example) - use write_phylip_Cluster - *********************************************************************/ - -void print_DistanceMatrix( FILE *handle, struct DistanceMatrix *mat ) { - unsigned int row, column; - - fprintf( handle, "Size:%d\n", mat->size); - - for(row=0; row < mat->size; row++) { - fprintf( handle, "%5d", row); - for(column=0; column <= row; column++) - fprintf( handle, "%10.5f", mat->data[row][column]); - fprintf( handle, "\n"); - } - fflush( handle ); -} - - - - -/********************************************************************* - FUNCTION: read_phylip_DistanceMatrix - DESCRIPTION: - This function creates a DistanceMatrix from the given input file. - It also crates a dummy alignment (sequences with just names) and - puts it in the given Alignment pointer - RETURNS: struct Cluster * - ARGS: - A file handle - A pointer to an Alignment pointer - NOTES: - The file is assumed to be the distance matrix file format used - by the phlip package: - - 4 - Name_1 0.0000 0.6776 0.6786 0.2342 - Name_2 0.6776 0.0000 0.1111 0.9999 - Name_3 0.6786 0.1111 0.0000 0.4444 - Name_4 0.2342 0.9999 0.4444 0.0000 - *********************************************************************/ - -struct DistanceMatrix *read_phylip_DistanceMatrix( FILE *handle, struct Alignment **aln_loc) { - struct DistanceMatrix *mat; - unsigned int size, i, j; - char identifier[11]; - double dist; - - /* The size of the matrix will be on the first line on its own */ - if (! fscanf( handle, "%d", &size )) - fatal_util( "Parse error: The first line should contain the size of matrix"); - - *aln_loc = (struct Alignment *) malloc_util( sizeof(struct Alignment )); - - (*aln_loc)->numseqs = size; - (*aln_loc)->seqs = (struct Sequence **) - malloc_util( size * sizeof( struct Sequence *)); - (*aln_loc)->length = 0; - mat = empty_DistanceMatrix( size ); - - - for (i=0; i < size; i++) { - /* The name should be exactly 10 chars, and the scanf should place a \0 - at the end, making 11 */ - fscanf( handle, "%s", identifier ); - /* Right; the rest of the line will consist of exactly 'size' floating - point numbers */ - (*aln_loc)->seqs[i] = empty_Sequence(); - (*aln_loc)->seqs[i]->name = (char *) malloc_util( 11 * sizeof(char)); - strcpy( (*aln_loc)->seqs[i]->name, identifier ); - for (j=0; j < size; j++) { - fscanf( handle, "%lf", &dist); - if (j <= i) - mat->data[i][j] = (Distance) dist; - } - } - - return mat; -} - - - -/********************************************************************* - FUNCTION: write_phylip_DistanceMatrix - DESCRIPTION: - This function takes the given DistanceMatrix and writes it to the - given file handle in phylip format. The alignment is needed for the - Sequence names - format - RETURNS: - ARGS: - A file handle - A DistanceMatrix pointer (cluster.h) - An Alignment pointer - NOTES: - The file is written in the distance matrix file format used - by the phlip package: - - 4 - Name_1 0.0000 0.6776 0.6786 0.2342 - Name_1 0.6776 0.0000 0.1111 0.9999 - Name_1 0.6786 0.1111 0.0000 0.4444 - Name_1 0.2342 0.9999 0.4444 0.0000 -*********************************************************************/ - -void write_phylip_DistanceMatrix( FILE *handle, - struct DistanceMatrix *mat, - struct Alignment *align) { - - unsigned int row, column; - - fprintf( handle, "\t%d\n", align->numseqs); - - for(row=0; row < align->numseqs; row++) { - fprintf( handle, "%10.10s", align->seqs[row]->name); - for(column=0; column < align->numseqs; column++) { - if (row > column ) - fprintf( handle, "%10.5f", mat->data[row][column]); - else - fprintf( handle, "%10.5f", mat->data[column][row]); - } - fprintf( handle, "\n"); - } - fflush( handle ); -} diff --git a/externalTools/quicktree_1.1/src/distancemat_merops.c b/externalTools/quicktree_1.1/src/distancemat_merops.c deleted file mode 100644 index ab5e4b8..0000000 --- a/externalTools/quicktree_1.1/src/distancemat_merops.c +++ /dev/null @@ -1,460 +0,0 @@ -/* Last edited: Feb 1 18:15 2002 (klh) */ -/********************************************************************** - ** FILE: distancemat.c - ** NOTES: - ** Functions and types for the manipulation of Distance Matrices - **********************************************************************/ - -#include "distancemat.h" - - -/*********************** static variables *****************************/ - -/* This is a table of estimated PAMs for a range of percentage-differences, - ranging from 75% dissimilarity, going up in 0.1% steps, to 93% - dissimilarity. For percentage dissimilarty outside this range, we either - use Kimura's formula (for < 75) or give an arbitrarily high distance - (for > 93) */ - -static int dayhoff_pams[]={ - 195, /* 75.0% observed d; 195 PAMs estimated = 195% estimated d */ - 196, /* 75.1% observed d; 196 PAMs estimated */ - 197, 198, 199, 200, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, - 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 236, 237, 238, 239, 240, 241, 243, 244, 245, - 246, 248, 249, 250, /* 250 PAMs = 80.3% observed d */ - 252, 253, 254, 255, 257, 258, - 260, 261, 262, 264, 265, 267, 268, 270, 271, 273, - 274, 276, 277, 279, 281, 282, 284, 285, 287, 289, - 291, 292, 294, 296, 298, 299, 301, 303, 305, 307, - 309, 311, 313, 315, 317, 319, 321, 323, 325, 328, - 330, 332, 335, 337, 339, 342, 344, 347, 349, 352, - 354, 357, 360, 362, 365, 368, 371, 374, 377, 380, - 383, 386, 389, 393, 396, 399, 403, 407, 410, 414, - 418, 422, 426, 430, 434, 438, 442, 447, 451, 456, - 461, 466, 471, 476, 482, 487, 493, 498, 504, 511, - 517, 524, 531, 538, 545, 553, 560, 569, 577, 586, - 595, 605, 615, 626, 637, 649, 661, 675, 688, 703, - 719, 736, 754, 775, 796, 819, 845, 874, 907, 945, - /* 92.9% observed; 945 PAMs */ - 988 /* 93.0% observed; 988 PAMs */ -}; - - - - -/********************************************************************* - FUNCTION: calc_DistanceMatrix - DESCRIPTION: - Produces a distance matrix from the given multiple alignment - RETURNS: struct DistanceMatrix - ARGS: - A DistanceMatrix to fill in - A multiple alignment - A boolean indicating whether or not random columns should be used - for purposes of bootstrapping - A boolean indicating whether the Kimura distance adjustment is to - be used or not. - NOTES: - 0. the given DistanceMatrix and Alignment should be of the same order - - 1. The matrix produced is in bottom-left triangular format; don't you - go trying to access that top-right section (I'm warning you...) - - 2. At the moment, the function calculates distance based on sequence - identity, using Kimura's function if that option is raised. - - 3. If use_rand_cols is true, then the matrix is constructed using - random sampling of columns, for the purposes of bootstrapping. At - the moment, the native function 'rand' is used to do this, suitable - seeded by time (by the caller). This may prove unsatisfactory... - - 4. Where no information is available to determine the distance - between two sequences, a value of twice the maximum observed - distance is assigned (inspiration from ISMB99 poster by Huson, - Smith and Warnow). - - *********************************************************************/ - -void calc_DistanceMatrix( struct DistanceMatrix *mat, - struct Alignment *aln, - unsigned int use_rand_cols, - unsigned int use_kimura ) { - - /* this function will take alignment and return a distance matrix */ - /* This gives a clear separation between tree making and distances */ - - unsigned int i, j, k, table_index, num_undefined_distances, mem_increment; - unsigned int *columnlist; - float residuecount, distance, max_observed_distance; - float **undefined_distances; - - columnlist = (unsigned int *) malloc_util( aln->length * sizeof(unsigned int)); - for (i=0; i < aln->length; i++) { - if (use_rand_cols) { - /* generate random column here */ - columnlist[i] = (unsigned int) rand() % aln->length; - } - else { - columnlist[i] = i; - } - } - - max_observed_distance = 0.0; - mem_increment = 10; - undefined_distances = NULL; - num_undefined_distances = 0; - - for( i=0; i < aln->numseqs; i++) { - mat->data[i][i] = 0.0; - for( j=0; j < i; j++ ) { - residuecount = distance = 0.0; - mat->data[i][j] = 0.0; - - for( k=0; k < aln->length; k++) { - if ( aln->seqs[i]->seq[columnlist[k]] == '.' || - aln->seqs[j]->seq[columnlist[k]] == '.' || - aln->seqs[i]->seq[columnlist[k]] == '-' || - aln->seqs[j]->seq[columnlist[k]] == '-' || - aln->seqs[i]->seq[columnlist[k]] == ' ' || - aln->seqs[j]->seq[columnlist[k]] == ' ') - continue; - - /* neither character is a gap, so proceed */ - residuecount += 1.0; - if ( aln->seqs[i]->seq[columnlist[k]] != aln->seqs[j]->seq[columnlist[k]]) - distance += 1.0; - } - - /* if residue count was zero here, there must have been a gap in every position; - in this case, %identity is undefined so a decision must be made to consider the - sequences 100% identical or 100% different. I go with the standard approach of - assigning twoce the maximum observed distance */ - - if (residuecount > 0) { - distance = distance / residuecount; - } - else { - distance = -1.0; - if (num_undefined_distances % mem_increment == 0) { - if (num_undefined_distances == 0) { - undefined_distances = (float **) - malloc_util( sizeof( float *) * mem_increment); - } - else { - undefined_distances = (float **) - realloc_util( undefined_distances, - (num_undefined_distances + mem_increment) * sizeof(float *)); - } - } - undefined_distances[num_undefined_distances++] = &(mat->data[i][j]); - /* distances should be zero, but may be slightly less due to floating point - arithmetic */ - } - - /* Use Kimura's formula to convert percentage dissimilarity to a distance */ - /* - if (use_kimura) { - if ( distance < 0.75) { - if (distance > 0.0) - distance = - log( 1.0 - distance - (distance * distance * 0.20) ); - } - else { - if (distance > 0.930) { - distance = 10.0; - } - else { - table_index = (int) ((distance*1000.0) - 750.0); - distance = (float) dayhoff_pams[ table_index ]; - distance /= 100.0; - } - } - } - */ - /********** for merops **********/ - if (distance > 0.83) - distance = 10.0; - else { - distance = log (1.0 - (distance / 0.83)) * -83.0; - distance /= 100.0; - } - /********************************/ - - if (distance > max_observed_distance) { - max_observed_distance = distance; - } - mat->data[i][j] = distance; - } - } - - /* before we go, lets find those undefined distances and replace them with - twice the maximum observed distance */ - - for (i=0; i < num_undefined_distances; i++ ) { - *undefined_distances[i] = 2 * max_observed_distance; - } - - columnlist = free_util( columnlist ); - if (undefined_distances != NULL) { - undefined_distances = free_util( undefined_distances ); - } -} - - - -/********************************************************************* - FUNCTION: clone_DistanceMatrix - DESCRIPTION: - Produces a brand new DistanceMatrix, identical to the source - RETURNS: struct DistanceMatrix - ARGS: - A source distane matrix - NOTES: - 1. The matrix produced is in bottom-left triangular format; don't you - go trying to access that top-right section (I'm warning you...) - *********************************************************************/ -struct DistanceMatrix *clone_DistanceMatrix( struct DistanceMatrix *source) { - unsigned int i,j; - struct DistanceMatrix *dest; - - if (source != NULL) { - dest = empty_DistanceMatrix( source->size ); - - for( i=0; i < dest->size; i++) { - for( j=0; j <= i; j++ ) { - dest->data[i][j] = source->data[i][j]; - } - } - } - else { - dest = NULL; - } - - return dest; -} - - - -/********************************************************************* - FUNCTION: empty_DistanceMatrix - DESCRIPTION: - Produces an empty distance matrixof the given size, uninitialised - RETURNS: struct DistanceMatrix - ARGS: - The size of the matrix to be created - NOTES: - 1. The matrix produced is in bottom-left triangular format; don't you - go trying to access that top-right section (I'm warning you...) - *********************************************************************/ -struct DistanceMatrix *empty_DistanceMatrix( unsigned int size) { - unsigned int i; - struct DistanceMatrix *mat; - - mat = (struct DistanceMatrix *) malloc_util(sizeof(struct DistanceMatrix)); - mat->size = size; - mat->data = (float **) malloc_util( mat->size * sizeof(float *) ); - - for( i=0; i < mat->size; i++) - mat->data[i] = (float *) malloc_util( (i+1) * sizeof(float) ); - - return mat; -} - - - -/********************************************************************* - FUNCTION: free_DistanceMatrix - DESCRIPTION: - Frees the memory for the given distance matrix - RETURNS: - ARGS: - struct DistanceMatrix * - NOTES: - *********************************************************************/ - -void *free_DistanceMatrix( struct DistanceMatrix *mat ) { - int i; - - if ( mat != NULL ) { - if (mat->data != NULL) { - for( i=0; i < mat->size; i++ ) { - if (mat->data[i] != NULL) - mat->data[i] = free_util( mat->data[i] ); - } - mat->data = free_util( mat->data ); - } - mat = free_util( mat ); - } - - return mat; -} - - - - -/********************************************************************** - FUNCTION: index_DistanceMatrix - DESCRIPTION: - indexes the given distance matrix with the given indices, - returning the appropraite distance. - RETURNS: distance (float) - ARGS: - A distance matrix * - row index - column index - NOTES: - This function is necessary to account for the fact that the distance - matrix may be implemented as a symmtrical or triangular matrix. - It therefore abstracts the internals of the distance matrix, at the - cost of a function call for each lookup (is this wise...?) - **********************************************************************/ - -float index_DistanceMatrix( struct DistanceMatrix *mat, - unsigned int i, - unsigned int j) { - if (i > j) - return mat->data[i][j]; - else - return mat->data[j][i]; -} - - -/********************************************************************* - FUNCTION: print_DistanceMatrix - DESCRIPTION: - Prints the given distance matrix. - RETURNS: - ARGS: - struct DistanceMatrix * - NOTES: - A DistanceMatrix does not exist in isolation in practice but as - part of a Cluster (this is to maintain the tight coupling between - the matrix and the sequences for which it is expressing the distances). - Therefore, to read or write a useful distance - matrix (for compatibility with the phylip package for example) - use write_phylip_Cluster - *********************************************************************/ - -void print_DistanceMatrix( FILE *handle, struct DistanceMatrix *mat ) { - unsigned int row, column; - - fprintf( handle, "Size:%d\n", mat->size); - - for(row=0; row < mat->size; row++) { - fprintf( handle, "%5d", row); - for(column=0; column <= row; column++) - fprintf( handle, "%10.5f", mat->data[row][column]); - fprintf( handle, "\n"); - } - fflush( handle ); -} - - - - -/********************************************************************* - FUNCTION: read_phylip_DistanceMatrix - DESCRIPTION: - This function creates a DistanceMatrix from the given input file. - It also crates a dummy alignment (sequences with just names) and - puts it in the given Alignment pointer - RETURNS: struct Cluster * - ARGS: - A file handle - A pointer to an Alignment pointer - NOTES: - The file is assumed to be the distance matrix file format used - by the phlip package: - - 4 - Name_1 0.0000 0.6776 0.6786 0.2342 - Name_2 0.6776 0.0000 0.1111 0.9999 - Name_3 0.6786 0.1111 0.0000 0.4444 - Name_4 0.2342 0.9999 0.4444 0.0000 - *********************************************************************/ - -struct DistanceMatrix *read_phylip_DistanceMatrix( FILE *handle, struct Alignment **aln_loc) { - struct DistanceMatrix *mat; - unsigned int size, i, j; - char identifier[11]; - float dist; - - /* The size of the matrix will be on the first line on its own */ - if (! fscanf( handle, "%d", &size )) - fatal_util( "Parse error: The first line should contain the size of matrix"); - - *aln_loc = (struct Alignment *) malloc_util( sizeof(struct Alignment )); - - (*aln_loc)->numseqs = size; - (*aln_loc)->seqs = (struct Sequence **) - malloc_util( size * sizeof( struct Sequence *)); - (*aln_loc)->length = 0; - mat = empty_DistanceMatrix( size ); - - - for (i=0; i < size; i++) { - /* The name should be exactly 10 chars, and the scanf should place a \0 - at the end, making 11 */ - fscanf( handle, "%s", identifier ); - /* Right; the rest of the line will consist of exactly 'size; floating - point numbers */ - (*aln_loc)->seqs[i] = empty_Sequence(); - (*aln_loc)->seqs[i]->name = (char *) malloc_util( 11 * sizeof(char)); - strcpy( (*aln_loc)->seqs[i]->name, identifier ); - for (j=0; j < size; j++) { - fscanf( handle, "%f", &dist); - if (j <= i) - mat->data[i][j] = dist; - } - } - - return mat; -} - - - -/********************************************************************* - FUNCTION: write_phylip_DistanceMatrix - DESCRIPTION: - This function takes the given DistanceMatrix and writes it to the - given file handle in phylip format. The alignment is needed for the - Sequence names - format - RETURNS: - ARGS: - A file handle - A DistanceMatrix pointer (cluster.h) - An Alignment pointer - NOTES: - The file is written in the distance matrix file format used - by the phlip package: - - 4 - Name_1 0.0000 0.6776 0.6786 0.2342 - Name_1 0.6776 0.0000 0.1111 0.9999 - Name_1 0.6786 0.1111 0.0000 0.4444 - Name_1 0.2342 0.9999 0.4444 0.0000 -*********************************************************************/ - -void write_phylip_DistanceMatrix( FILE *handle, - struct DistanceMatrix *mat, - struct Alignment *align) { - - unsigned int row, column; - - fprintf( handle, "\t%d\n", align->numseqs); - - for(row=0; row < align->numseqs; row++) { - fprintf( handle, "%10.10s", align->seqs[row]->name); - for(column=0; column < align->numseqs; column++) { - if (row > column ) - fprintf( handle, "%10.5f", mat->data[row][column]); - else - fprintf( handle, "%10.5f", mat->data[column][row]); - } - fprintf( handle, "\n"); - } - fflush( handle ); -} diff --git a/externalTools/quicktree_1.1/src/options.c b/externalTools/quicktree_1.1/src/options.c deleted file mode 100644 index 23a2245..0000000 --- a/externalTools/quicktree_1.1/src/options.c +++ /dev/null @@ -1,96 +0,0 @@ -/* Last edited: Feb 1 15:45 2002 (klh) */ -/********************************************************************** - ** FILE: options.c - ** DESCRIPTION: - ** Rudimentary provision of command-line options - **********************************************************************/ - -#include "options.h" - - - -/********************************************************************* - FUNCTION: get_option - DESCRIPTION: - Gets an option from the given command line - RETURNS: - 1, if a valid option was found - 0, if no valid option was found and option parsing is therefore - complete - ARGS: - NOTES: -*********************************************************************/ -unsigned int get_option(int argc, - char **argv, - struct Option *opt, - unsigned int num_opts, - char *usage, - unsigned int *ret_optindex, - char **ret_optname, - char **ret_optarg) { - - static int optindex = 1; /* init to 1 on first call */ - static char *optptr = NULL; /* ptr to next valid switch */ - - unsigned int i, arglen, matches, opti = 0; - - /* Check to see if we've run out of options. '-' on its own is not an option */ - - if (optindex >= argc || argv[optindex][0] != '-' || strcmp(argv[optindex], "-") == 0) { - *ret_optindex = optindex; - *ret_optarg = NULL; - *ret_optname = NULL; - return 0; - } - - /* We have an option. All options are treated as 'full' optiions, - including single letter ones, which means you can't join - single letter options with -abc; use -a -b -c */ - - if (optptr == NULL && (argv[optindex][0] == '-')) { - if ((optptr = strchr(argv[optindex], '=')) != NULL) { - *optptr = '\0'; - optptr++; - } - - arglen = strlen(argv[optindex]); - matches = 0; - for (i = 0; i < num_opts; i++) { - if (strncmp(opt[i].name, argv[optindex], arglen) == 0) { - matches++; - opti = i; - } - } - if (matches > 1 && arglen != strlen(opt[opti].name)) - fatal_util("Option \'%s\' is ambiguous.\n%s", argv[optindex], usage); - if (matches == 0) - fatal_util("No such option as \'%s\'.\n%s", argv[optindex], usage); - - *ret_optname = opt[opti].name; - - if (opt[opti].type != NO_ARGS) { - if (optptr != NULL) { - *ret_optarg = optptr; - optptr = NULL; - optindex++; - } - else if (optindex+1 >= argc) { - fatal_util("Option %s needs an argument\n%s", opt[opti].name, usage); - } - else { - *ret_optarg = argv[optindex+1]; - optindex += 2; - } - } - else { - if (optptr != NULL) { - fatal_util("Option %s does not take any arguments\n%s", opt[optindex].name, usage); - } - *ret_optarg = NULL; - optindex++; - } - } - - *ret_optindex = optindex; - return 1; -} diff --git a/externalTools/quicktree_1.1/src/quicktree.c b/externalTools/quicktree_1.1/src/quicktree.c deleted file mode 100644 index d5b7d0a..0000000 --- a/externalTools/quicktree_1.1/src/quicktree.c +++ /dev/null @@ -1,207 +0,0 @@ -/* Last edited: Feb 1 18:22 2002 (klh) */ -/*********************************************************************** - ** FILE: quicktree.c - ** NOTES: - ** This program does one of three things: - ** 1. Given an aligment, construct a distance matrix. - ** 2. Given a distance matrix, build a tree - ** 3. Given an aligment, build a tree - ** Which of these modes is active is dependent upon the command options - ** - ***********************************************************************/ - -#include "options.h" -#include "util.h" -#include "align.h" -#include "cluster.h" -#include "buildtree.h" -#include "distancemat.h" -#include "tree.h" - - -/********************* command-line options * ************************/ - -static char usage[] = "\ -Usage: quicktree [-options] \n\ -Options:\n\ --in : input file is a distance matrix in phylip format (m)\n\ - or an alignment in stockholm format* (a, default)\n\ --out : output is a distance matrix in phylip format (m) or\n\ - a tree in New Hampshire format\n\n\ -Advanced options :\n\ --upgma : Use the UPGMA method to construct the tree\n\ - (ignored for distance matrix outputs)\n\ --kimura : Use the kimura translation for pairwise distances\n\ - (ignored for distance matrix inputs)\n\ --boot : Calcuate bootstrap values with n iterations\n\ - (ignored for distance matrix outputs)\n\n\ -*Use sreformat, part of the HMMer package to convert your alignment to Stockholm format\n"; - -static struct Option options[] = { - { "-in", CHAR_ARG }, - { "-out", CHAR_ARG }, - { "-upgma", NO_ARGS }, - { "-kimura", NO_ARGS }, - { "-boot", INT_ARG }, - { "-h", NO_ARGS } -}; - -static unsigned int use_kimura = 0; -static unsigned int calc_bootstraps = 0; -static unsigned int use_upgma = 0; -static unsigned int input_is_matrix = 0; -static unsigned int output_is_matrix = 0; - - -static void quicktree( FILE *input) { - unsigned int trial; - struct Alignment *aln, *cons_aln = NULL; - struct DistanceMatrix *mat; - struct ClusterGroup *group; - struct Tree *myTree, *testTree; - - struct Tree *(*tree_func)(struct ClusterGroup *, unsigned int); - /* step 1: get the distance matrix (either build or read it) */ - - - if (input_is_matrix) { - - mat = read_phylip_DistanceMatrix( input, &aln ); - - fclose( input ); - - /* Note that the alignment here contains no sequences, just names, - so there is no point in trying to merge identical sequences, hence - the FALSE argument - - */ - - group = alignment_to_ClusterGroup( aln, FALSE ); - group->matrix = mat; - - } - else { - /* input must be an alignment */ - - if ( ( aln = read_Stockholm_Alignment( input )) == NULL) - fatal_util( "Parse error in alignment file: Must be in MUL format"); - fclose( input ); - - if (output_is_matrix) { - mat = empty_DistanceMatrix( aln->numseqs ); - calc_DistanceMatrix( mat, aln, FALSE, use_kimura ); - write_phylip_DistanceMatrix( stdout, mat, aln ); - mat = free_DistanceMatrix( mat ); - return; - } - - group = alignment_to_ClusterGroup( aln, TRUE ); - aln = free_Alignment( aln ); - cons_aln = consensus_aln_from_ClusterGroup( group ); - group->matrix = empty_DistanceMatrix( group->numclusters ); - calc_DistanceMatrix( group->matrix, cons_aln, FALSE, use_kimura ); - - } - - /* step 2 produce tree */ - - tree_func = use_upgma ? &UPGMA_buildtree : &neighbour_joining_buildtree; - - myTree = (*tree_func)( group, calc_bootstraps ); - - if (calc_bootstraps) { - for (trial=0; trial < calc_bootstraps; trial++) { - calc_DistanceMatrix( group->matrix, cons_aln, TRUE, use_kimura ); - testTree = (*tree_func)( group, calc_bootstraps ); - update_bootstraps_Tree( myTree, testTree, group->numclusters ); - testTree = free_Tree( testTree ); - } - scale_bootstraps_Tree( myTree, calc_bootstraps ); - cons_aln = free_Alignment( cons_aln ); - } - - write_newhampshire_Tree( stdout, myTree, calc_bootstraps ); - - aln = free_Alignment( aln ); - group = free_ClusterGroup( group ); - myTree = free_Tree( myTree ); - -} - - - -/********************************************************************* - MAIN - *********************************************************************/ - -int main (int argc, char *argv[]) { - - FILE *input; - char *fname; - - char *optname; /* name of option found by getoption */ - char *optarg; /* argument found by getoption */ - unsigned int optindex; /* index in argv[] */ - - /**********************************/ - /** process command line options **/ - /**********************************/ - - while (get_option( argc, - argv, - options, - sizeof(options) / sizeof( struct Option ), - usage, - &optindex, - &optname, - &optarg )){ - if (strcmp(optname, "-upgma") == 0) use_upgma = 1; - else if (strcmp(optname, "-kimura") == 0) use_kimura = 1; - else if (strcmp(optname, "-boot") == 0) calc_bootstraps = atoi( optarg ); - else if (strcmp(optname, "-in") == 0) { - if (optarg[0] != 'm' && optarg[0] != 'a') - fatal_util("Error: Incorrect use of '-in' optio\n%s\n", usage ); - - if (optarg[0] == 'm') - input_is_matrix = 1; - else if (optarg[0] == 'a') - input_is_matrix = 0; - } - else if (strcmp(optname, "-out") == 0) { - if (optarg[0] != 'm' && optarg[0] != 't') - fatal_util("Error: Incorrect use of '-out' option\n%s\n", usage ); - - if (optarg[0] == 'm') - output_is_matrix = 1; - else if (optarg[0] == 't') - output_is_matrix = 0; - - } - else if (strcmp(optname, "-h") == 0) { - fprintf( stderr, "%s", usage ); - exit(0); - } - } - - if (argc - optindex != 1) { - fatal_util("Fatal error: Incorrect number of arguements.\n%s\n", usage ); - } - - fname = argv[optindex]; - - /* do some options combination checking - some combinations do not make sense */ - - if (input_is_matrix && use_kimura) - fatal_util("You can only use kimura when giving an aligment\n%s\n", usage ); - - if ( (input_is_matrix || output_is_matrix) && calc_bootstraps) - fatal_util("You can't do bootstrapping in matrix mode. You need an alignment\n%s\n", usage ); - - - if ((input = fopen( fname, "r" )) == NULL) - fatal_util( "Could not open file %s for reading", fname ); - - quicktree( input ); - - exit(0); -} diff --git a/externalTools/quicktree_1.1/src/sequence.c b/externalTools/quicktree_1.1/src/sequence.c deleted file mode 100644 index 4bdef89..0000000 --- a/externalTools/quicktree_1.1/src/sequence.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Last edited: Feb 1 18:21 2002 (klh) */ -/********************************************************************** - ** FILE: sequence.c - ** NOTES: - ** Functions and structures for the manipulation of protein - ** sequences. Only minimal functionality is needed - **********************************************************************/ - -#include "sequence.h" - - -/********************************************************************** - FUNCTION: clone_Sequence - DESCRIPTION: - Performs a deep copy of the given Sequence and returns it - ARGS: - A Sequenced pointer (sequence.h) - RETURNS: - A pointer to a Sequence structure - NOTES: - **********************************************************************/ - -struct Sequence *clone_Sequence( struct Sequence *source) { - unsigned int i; - struct Sequence *dest = NULL; - - if (source != NULL) { - dest = empty_Sequence(); - - dest->name = (char *) malloc_util( (strlen(source->name)+1) * sizeof(char)); - strcpy( dest->name, source->name ); - dest->length = source->length; - if (source->length) - dest->seq = (char *) malloc_util( dest->length * sizeof( char )); - for( i=0; i < dest->length; i++) { - dest->seq[i] = source->seq[i]; - } - if (source->sec_struct != NULL) { - dest->sec_struct = (char *) malloc_util( dest->length * sizeof( char )); - for (i=0; i < dest->length; i++) { - dest->sec_struct[i] = source->sec_struct[i]; - } - } - if (source->surf_acc != NULL) { - dest->surf_acc = (char *) malloc_util( dest->length * sizeof( char )); - for (i=0; i < dest->length; i++) { - dest->surf_acc[i] = source->surf_acc[i]; - } - } - if (source->post_prob != NULL) { - dest->post_prob = (char *) malloc_util( dest->length * sizeof( char )); - for (i=0; i < dest->length; i++) { - dest->post_prob[i] = source->post_prob[i]; - } - } - if (source->lig_bind != NULL) { - dest->lig_bind = (char *) malloc_util( dest->length * sizeof( char )); - for (i=0; i < dest->length; i++) { - dest->lig_bind[i] = source->lig_bind[i]; - } - } - } - - return dest; -} - - - -/********************************************************************** - FUNCTION: empty_Sequence - DESCRIPTION: - Creates and returns an new, empty Sequence object - ARGS: - RETURNS: - A pointer to a Sequence structure - NOTES: - **********************************************************************/ -struct Sequence *empty_Sequence( void ) { - struct Sequence *theseq; - - theseq = (struct Sequence *) malloc_util( sizeof(struct Sequence)); - theseq->length = 0; - theseq->name = NULL; - theseq->seq = NULL; - theseq->sec_struct = NULL; - theseq->surf_acc = NULL; - theseq->post_prob = NULL; - theseq->lig_bind = NULL; - - return theseq; -} - - - - -/********************************************************************** - FUNCTION: free_Sequence - DESCRIPTION: - frees the memory occupied by the given Sequence reference - ARGS: - A pointer to a struct Sequence - RETURNS: - The NULL pointer - NOTES: - **********************************************************************/ -void *free_Sequence( struct Sequence *theseq ) { - - if (theseq != NULL) { - if (theseq->name != NULL) - theseq->name = free_util( theseq->name); - if (theseq->seq != NULL) - theseq->seq = free_util( theseq->seq); - if (theseq->sec_struct != NULL) - theseq->sec_struct = free_util( theseq->sec_struct); - if (theseq->surf_acc != NULL) - theseq->surf_acc = free_util( theseq->surf_acc); - if (theseq->post_prob != NULL) - theseq->post_prob = free_util( theseq->post_prob); - if (theseq->lig_bind != NULL) - theseq->lig_bind = free_util( theseq->lig_bind); - - theseq = free_util( theseq ); - } - return theseq; -} - - - - - - diff --git a/externalTools/quicktree_1.1/src/tree.c b/externalTools/quicktree_1.1/src/tree.c deleted file mode 100644 index 662fc2d..0000000 --- a/externalTools/quicktree_1.1/src/tree.c +++ /dev/null @@ -1,956 +0,0 @@ -/* Last edited: Mar 18 11:55 2002 (klh) */ -/********************************************************************** - ** FILE: tree.c - ** NOTES: - ** Functions for the manipulation of trees - **********************************************************************/ - -#include "tree.h" - - - -/********************************************************************* - FUNCTION: assign_nodenumbers_Tnode - DESCRIPTION: - This function assigns node numbers to the internal nodes of the - given Tnode, starting from the given, and returns the next free - nodenumner - RETURNS: unsigned int - ARGS: - struct Tnode * (tree) - unsigned int (starting node number) - NOTES: - *********************************************************************/ -unsigned int assign_nodenumbers_Tnode( struct Tnode *node, unsigned int start) { - - if (node != NULL) { - start += assign_nodenumbers_Tnode( node->left, start ); - start += assign_nodenumbers_Tnode( node->right, start ); - - node->nodenumber = start++; - } - - return start; -} - - - -/********************************************************************* - FUNCTION: clone_Tnode - DESCRIPTION: - This function makes a complete copy of the tree rooted at the given - node and returns it - RETURNS: Tnode * - ARGS: - struct Tnode * - NOTES: - *********************************************************************/ -struct Tnode *clone_Tnode( struct Tnode *source) { - struct Tnode *dest = NULL; - - if (source != NULL) { - dest = (struct Tnode *) calloc_util(1, sizeof( struct Tnode ) ); - - dest->distance = source->distance; - dest->nodenumber = source->nodenumber; - dest->bootstrap = source->bootstrap; - dest->clust = clone_Cluster( source->clust ); - if ( (dest->left = clone_Tnode( source->left )) != NULL) - dest->left->parent = dest; - if ( (dest->right = clone_Tnode( source->right )) != NULL) - dest->right->parent = dest; - } - - return dest; -} - - - -/********************************************************************* - FUNCTION: clone_Tree - DESCRIPTION: - This function makes a complete copy of the Tree and returns it - RETURNS: struct Tree * - ARGS: - struct Tree * - NOTES: - *********************************************************************/ -struct Tree *clone_Tree( struct Tree *source) { - struct Tree *dest = NULL; - - if ( source != NULL ) { - dest = (struct Tree *) malloc_util( sizeof( struct Tree ) ); - dest->numnodes = source->numnodes; - dest->child[0] = clone_Tnode( source->child[0] ); - dest->child[1] = clone_Tnode( source->child[1] ); - dest->child[2] = clone_Tnode( source->child[2] ); - } - - return dest; - -} - - - - -/********************************************************************* - FUNCTION: compare_to_bootstrap_sample_Tnode - DESCRIPTION: - Updates the bootstrap values of the given Tnode, according to - the topology of the given sample Tnode - RETURNS: - ARGS: - Destination Tnode - Sample Tnode - The number of leaf nodes in each tree - Boolean for whether the tree is binary or not - NOTES: - This function assumes that the given trees have been created by - calling either neighbourjoin_buildtree or UPGMA_buildtree with - the bootstrap boolean arguement set to true. A fatal error results - if this is not the case. This is due to the fact that the information - needed for the tree comparisons is determined when the trees are - constructed - *********************************************************************/ -void compare_to_bootstrap_sample_Tnode( struct Tnode *dest, - struct Tnode *sample, - unsigned int numleaves, - unsigned int is_binary) { - unsigned int matchcounter, i; - - if (dest != NULL) { - if (dest->child_ids != NULL) { - - /* we have to explore every non-terminal node of sample to see - if the bit pattern is the same, or a mirror image. If yes, then - this sub-tree exists in sample. The mirror image is to take care - of the fact that trichotomius trees may be isomorphic but - 'centred' at a different node. - - For non-trichotomous (i.e. rooted binary) trees, it is erroneous - to allow these 'mirror image' cases. It is easy to found out what - sort of trees we have by examining the child fields in one of the - trees. If only one of them is non-null, then we have a rooted - binary tree. - */ - - if (sample != NULL) { - if (sample->child_ids != NULL) { - matchcounter = 0; - for(i=0; i < numleaves; i++) { - if (dest->child_ids[i] == sample->child_ids[i]) { - matchcounter++; - } - } - if ((matchcounter == numleaves) || (matchcounter == 0 && ! is_binary)) { - dest->bootstrap++; - /* printf ("Incrementing node %d...\n", dest->nodenumber ); */ - } - - compare_to_bootstrap_sample_Tnode( dest, sample->left, numleaves, is_binary ); - compare_to_bootstrap_sample_Tnode( dest, sample->right, numleaves, is_binary ); - } - } - } - } -} - - - - -/********************************************************************* - FUNCTION: empty_Tree - DESCRIPTION: - Creates and returns a tree with null nodes - RETURNS: struct Tree * (trees.h) - ARGS: - NOTES: - *********************************************************************/ - -struct Tree *empty_Tree( void ) { - struct Tree *ret; - - ret = (struct Tree *) malloc_util(sizeof( struct Tree )); - ret->child[0] = NULL; - ret->child[1] = NULL; - ret->child[2] = NULL; - ret->numnodes = 0; - - return ret; -} - - - -/********************************************************************* - FUNCTION: free_Tnode - DESCRIPTION: - This function releases the memory used by this Tnode and all of its - children - RETURNS: A null pointer - ARGS: - struct Tnode * - NOTES: - *********************************************************************/ - -void *free_Tnode( struct Tnode *tn ) { - if ( tn != NULL ) { - tn->clust = free_Cluster( tn->clust ); - tn->left = free_Tnode( tn->left ); - tn->right = free_Tnode( tn->right ); - if (tn->child_ids != NULL) { - tn->child_ids = free_util( tn->child_ids ); - } - tn = free_util( tn ); - } - return tn; - -} - - - -/********************************************************************* - FUNCTION: free_Tree - DESCRIPTION: - This function releases the memory used br the Tnode chain in the - given Tree - RETURNS: A null pointer - ARGS: - struct Tree - NOTES: - *********************************************************************/ - -void *free_Tree( struct Tree *t) { - if ( t != NULL ) { - t->child[0] = free_Tnode( t->child[0] ); - t->child[1] = free_Tnode( t->child[1] ); - t->child[2] = free_Tnode( t->child[2] ); - t = free_util( t ); - } - return t; -} - - - -/********************************************************************* - FUNCTION: get_root_Tnode - DESCRIPTION: This function takes a three node tree (struct Tree), and - returns a Tnode as the 'root' of the tree. The root is inserted - somewhat arbitraily between the three top-level nodes - RETURNS: struct Tnode * - ARGS: struct Tree - NOTES: - The nodes of the given tree are cloned for use. This means - that the old tree is still available and safe on return, and must - be freed when finished with. The rooted tree returned by this - function must be freed by a call to free_Tnode - *********************************************************************/ - -struct Tree *get_root_Tnode( struct Tree *source ) { - struct Tnode *focal, *root, *children[3]; - struct Tree *ret; - unsigned int rootleft, focalleft, focalright; - Distance maxdist; - - /***** Method ************** - 0. Clone the given tree - 1. Create the imaginary node between the three nodes in the Tree - 2. Create a root node; - **************************/ - - children[0] = clone_Tnode( source->child[0] ); - children[1] = clone_Tnode( source->child[1] ); - children[2] = clone_Tnode( source->child[2] ); - - focal = new_interior_Tnode( source->numnodes ); - root = new_interior_Tnode( source->numnodes + 1 ); - - /* arbitrarity choose halfway along the longest branch between - the three nodes as the position for the root */ - - maxdist = children[0]->distance; - rootleft = 0; - focalleft = 1; - focalright = 2; - if (children[1]->distance > maxdist) { - rootleft = 1; - focalleft = 0; - focalright = 2; - } - if (children[2]->distance > maxdist) { - rootleft = 2; - focalleft = 0; - focalright = 1; - } - - /* sort out distances; root node has zero distances */ - - children[rootleft]->distance = children[rootleft]->distance * 0.5; - focal->distance = children[rootleft]->distance; - - /* now sort out the links */ - - root->right = focal; - root->left = children[rootleft]; - focal->parent = children[rootleft]->parent = root; - - focal->left = children[focalleft]; - focal->right = children[focalright]; - children[focalleft]->parent = children[focalright] = focal; - - ret = empty_Tree(); - ret->child[0] = root; - ret->numnodes = source->numnodes + 2; - - return ret; -} - - - -/********************************************************************* - FUNCTION: new_interior_Tnode (unsigned int) - DESCRIPTION: - This function handles the simple task of allocating the space - for a new interior (non-leaf) tree node, filling it with what it - knows, and returning it. - RETURNS: struct Tnode * (trees.h) - ARGS: - A integer to hold the node number. - NOTES: - This function s for creating internal nodes, which have no string - id but just a number identifier - *********************************************************************/ - -struct Tnode *new_interior_Tnode( unsigned int label ) { - struct Tnode *newNode; - - newNode = (struct Tnode *) calloc_util(1, sizeof(struct Tnode)); - newNode->left = NULL; - newNode->right = NULL; - newNode->parent = NULL; - newNode->distance = 0.0; - newNode->nodenumber = label; - newNode->clust = NULL; - newNode->bootstrap = 0; - newNode->child_ids = NULL; - - return newNode; -} - - - - - -/********************************************************************* - FUNCTION: new_leaf_Tnode(int, char *) - DESCRIPTION: - This function handles the simple task of allocating the space - for a new tree node, filling it with what it knows, and - returning it. - RETURNS: struct Tnode * (trees.h) - ARGS: - A integer to hold the sequence number associated with the node - The name of the node - NOTES: - This function is for creating leaf nodes, which have a name. - *********************************************************************/ - -struct Tnode *new_leaf_Tnode(unsigned int label, struct Cluster *given) { - struct Tnode *newNode; - - newNode = new_interior_Tnode( label ); - newNode->clust = given; - - return newNode; -} - - - -/********************************************************************* - FUNCTION: read_newhampshire_Tnode - DESCRIPTION: - Construct a Tnode from the given file handle - RETURNS: The total number of nodes constructed as a result of the call - ARGS: - File handle (assumed in New Hampshire format) - NOTES: Due to the fact that the neighbourjoining implementation presented - in these modules has 'clusters' of sequences at the leaf nodes; - This means that the written tree will no longer be binary, so this - method wil no longer read in the trees produced by - write_newhampshire_Tree. I should look into ways around this - *********************************************************************/ - -unsigned int read_newhampshire_Tnode( FILE *handle, - struct Tnode **nodeptrptr, - struct Tnode *parent, - unsigned int nodecounter ) { - - char c; - unsigned int index; - struct Sequence *newseq; - double distance; - - - fscanf( handle, "%1s", &c); - - if ( c == '(' ) { - /* we do not know the node number until we have parsed the children, - so give it the value zero for now */ - - *nodeptrptr = new_interior_Tnode( 0 ); - - nodecounter += read_newhampshire_Tnode( handle, - &((*nodeptrptr)->left), - *nodeptrptr, - nodecounter ); - - fscanf( handle, "%1s", &c); /* should be , */ - if ( c != ',') - fatal_util( "Parse error: ',' expected"); - - nodecounter += read_newhampshire_Tnode( handle, - &((*nodeptrptr)->right), - *nodeptrptr, - nodecounter ); - - /* (*nodeptrptr)->nodenumber = nodecounter++; */ - - fscanf( handle, "%1s", &c); /* should be ) */ - if ( c != ')') - fatal_util( "Parse error: ')' expected"); - fscanf( handle, "%1s", &c); /* should be : */ - if ( c != ':') - fatal_util( "Parse error: ':' expected"); - if (!fscanf( handle, "%lf", &distance )) - fatal_util( "Parse error: floating point number expexted"); - - } - else { /* Must be the first char of an identifier */ - ungetc( c, handle ); - - newseq = empty_Sequence(); - newseq->name = (char *) malloc_util( MAX_NAME_LENGTH * sizeof( char ) ); - - for( index=0; (newseq->name[index] = fgetc( handle )) != ':'; index++); - newseq->name[index] = '\0'; - - if (!fscanf( handle, "%lf", &distance )) - fatal_util( "Parse error: floating point number expexted"); - - *nodeptrptr = new_leaf_Tnode( nodecounter++, single_Sequence_Cluster( newseq ) ); - } - - (*nodeptrptr)->parent = parent; - (*nodeptrptr)->distance = distance; - - return nodecounter; -} - - - -/********************************************************************* - FUNCTION: read_newhampshire_Tree - DESCRIPTION: - Constructs a tree from the given file handle - RETURNS: Tree * - ARGS: A handle to the file (assumed in New Hamshire format) - NOTES: - Numbering of internal nodes is abandoned in favour of giving leaf - nodes numbers from 0 to the number of leaves in the tree. This makes - them handy indices into a distance matrix for example - *********************************************************************/ - -struct Tree *read_newhampshire_Tree( FILE *handle ) { - unsigned int numnodes = 0; - char c; - - struct Tree *thetree = empty_Tree(); - - fscanf( handle, "("); - - numnodes += read_newhampshire_Tnode( handle, - &thetree->child[0], - NULL, - numnodes); - - fscanf( handle, "%1s", &c ); /* should be , */ - if ( c != ',') - fatal_util( "Parse error: ',' expected"); - - numnodes += read_newhampshire_Tnode( handle, - &thetree->child[1], - NULL, - numnodes); - - fscanf( handle, "%1s", &c ); /* should be , */ - if ( c != ',') - fatal_util( "Parse error: ',' expected"); - - numnodes += read_newhampshire_Tnode( handle, - &thetree->child[2], - NULL, - numnodes); - - fscanf( handle, "%1s", &c); - if ( c != ')') - fatal_util( "Parse error: ')' expected"); - fscanf( handle, "%1s", &c); - if ( c != ';') - fatal_util( "Parse error: ';' expected"); - - numnodes += assign_nodenumbers_Tnode( thetree->child[0], numnodes ); - numnodes += assign_nodenumbers_Tnode( thetree->child[1], numnodes ); - numnodes += assign_nodenumbers_Tnode( thetree->child[2], numnodes ); - thetree->numnodes = numnodes; - - return thetree; - -} - - - -/********************************************************************* - FUNCTION: scale_bootstraps_Tnode - DESCRIPTION: - This function traverses the given Tnode, dividing the bootstrap - values by the given number - RETURNS: - ARGS: - Tnode - A the number of bootstrap iterations that were performed - NOTES: - - *********************************************************************/ -void scale_bootstraps_Tnode( struct Tnode *node, unsigned int iters) { - - if (node != NULL) { - node->bootstrap = (int) (((double) node->bootstrap / (double) iters) * 100.0); - scale_bootstraps_Tnode( node->left, iters); - scale_bootstraps_Tnode( node->right, iters); - } - -} - - -/********************************************************************* - FUNCTION: scale_bootstraps_Tree - DESCRIPTION: - This function traverses the gieven tree, dividing the bootstrap - values by the given number - RETURNS: - ARGS: - Tree - A the number of bootstrap iterations that were performed - NOTES: - - *********************************************************************/ -void scale_bootstraps_Tree( struct Tree *thetree, unsigned int iters) { - - if (thetree != NULL) { - /* The first node will always be defined...(he says) */ - scale_bootstraps_Tnode( thetree->child[0], iters ); - if (thetree->child[1] != NULL) { - scale_bootstraps_Tnode( thetree->child[1], iters ); - if (thetree->child[2] != NULL) { - scale_bootstraps_Tnode( thetree->child[2], iters ); - } - } - } -} - - - -/********************************************************************* - FUNCTION: update_bootstraps_Tree - DESCRIPTION: - Updates the bootstrap values of the destination tree, according to - the topology of the given sample tree - RETURNS: - ARGS: - Destination tree - Sample tree - the number of leaf nodes in the tree - NOTES: - This function assumes that the given trees have been created by - calling either neighbourjoin_buildtree or UPGMA_buildtree with - the bootstrap boolean arguement set to true. A fatal error results - if this is not the case - - Another thing to note is that the method uses node numbers for - comparisons. This means that both ethe sample and reference trees - must have been built from the same initial list of nodes, which - is fine for bootstrapping, because the leaf nodes are stored in - the order in which appear in the alignment - *********************************************************************/ -void update_bootstraps_Tree( struct Tree *dest, struct Tree *sample, - unsigned int numleaves) { - unsigned int is_binary,i,j; - - is_binary = ( dest->child[1] == NULL && dest->child[2] == NULL )?1:0; - - for (i=0; i < 3; i++) { - for (j=0; j < 3; j++) { - update_bootstraps_Tnode( dest->child[i], - sample->child[j], - numleaves, - is_binary ); - } - } -} - - - -/********************************************************************* - FUNCTION: update_bootstraps_Tnode - DESCRIPTION: - Updates the bootstrap values of the given Tnode, according to - the topology of the given sample Tnode - RETURNS: - ARGS: - Destination Tnode - Sample Tnode - The number of leaf nodes in each tree - Boolean for whether the tree is binary or not - NOTES: - This function assumes that the given trees have been created by - calling either neighbourjoin_buildtree or UPGMA_buildtree with - the bootstrap boolean arguement set to true. A fatal error results - if this is not the case - *********************************************************************/ -void update_bootstraps_Tnode( struct Tnode *dest, - struct Tnode *sample, - unsigned int numleaves, - unsigned int is_binary) { - - - compare_to_bootstrap_sample_Tnode( dest, sample, numleaves, is_binary); - if (dest != NULL) { - update_bootstraps_Tnode( dest->left, sample, numleaves, is_binary); - update_bootstraps_Tnode( dest->right, sample, numleaves, is_binary); - } -} - - - - -/********************************************************************* - FUNCTION: write_clustering_data_Tnode - DESCRIPTION: - This routine prints a text description of the clustering details - of the given Tnode. It was written for the old implementation, - where leaves were named "leaf_1", "leaf_2" etc, and it would - often be the case that each leaf would contain several sequences. - With the current implementation, this function is not used; a - new-hampshire output of each cluster is printed in-situ, preserving - sequence names from the original alignment - RETURNS: - ARGS: - File handle - TNode * - NOTES: - *********************************************************************/ -void write_clustering_data_Tnode( FILE *handle, struct Tnode *node) { - unsigned int i; - - if (node != NULL) { - if (node->left == NULL && node->right == NULL && node->clust != NULL) { - /* we have a leaf node */ - if (node->clust->clustersize == 0 || node->clust->members == NULL) - fatal_util("Fatal Error: encountered a leaf node with no cluster members"); - else if (node->clust->clustersize > 1) { - fprintf( handle, "Cluster_%d:\n", node->nodenumber); - for( i=0; i < node->clust->clustersize; i++) { - if ( i == 0 ) - fprintf( handle, "\t" ); - else if ( i % 4 == 0 ) - fprintf( handle, "\n\t" ); - else - fprintf( handle, ", "); - fprintf( handle, "%s", node->clust->members[i]->name); - } - fprintf( handle, "\n\n"); - } - } - else { - write_clustering_data_Tnode( handle, node->left ); - write_clustering_data_Tnode( handle, node->right ); - } - } -} - - - -/********************************************************************* - FUNCTION: write_debug_Tnode - DESCRIPTION: - Writes the given Tnode to the give file handle in 'debug' format - RETURNS: - ARGS: - File handle - TNode * - Integer offset - NOTES: - *********************************************************************/ - -void write_debug_Tnode( FILE *handle, struct Tnode *node, unsigned int offset) { - unsigned int i,j; - - if (node != NULL) { - /* We need to determine whether the node is a leaf or internal; - since in this implementation internal nodes do not have names, - it is sufficient to check the nodes name for nullness; however, - this precludes the possibilities of internal nodes being given - names in the future, hence the check for internalness is made - on the basis of the nullness of the children. - */ - - if ( node->left == NULL && node->right == NULL ) { - /* this is a leaf node, so its cluster must have members; pain if not */ - if (node->clust->clustersize == 0 || node->clust->members == NULL) - fatal_util( "Fatal Error: encountered a leaf node with no cluster info"); - else { - for (i=0; i < node->clust->clustersize; i++) { - for (j=0; j < offset; j++) fprintf( handle, " "); - /* all leaves in the cluster are printed at the same offset */ - fprintf( handle, - "%d:%s:%.5f\n", - node->nodenumber, - node->clust->members[i]->name, - node->distance); - } - } - } - else if ( node->left != NULL && node->right != NULL ) { - for (j=0; j < offset; j++) fprintf( handle, " "); - fprintf(handle, "Node %d:%.5f\n", node->nodenumber, node->distance); - write_debug_Tnode( handle, node->left, offset+2); - write_debug_Tnode( handle, node->right, offset+2); - } - /* else do nothing */ - - fflush( handle ); - } -} - - - -/********************************************************************* - FUNCTION: write_debug_Tree - DESCRIPTION: - prints the given Tree in a format suitable for debugging - RETURNS: - ARGS: - File handle - Tree * - NOTES: - *********************************************************************/ - -void write_debug_Tree( FILE *handle, struct Tree *thetree) { - if (thetree != NULL) { - write_debug_Tnode( handle, thetree->child[0], 0 ); - write_debug_Tnode( handle, thetree->child[1], 0 ); - write_debug_Tnode( handle, thetree->child[2], 0 ); - - fflush( handle ); - } - -} - - - -/********************************************************************* - FUNCTION: write_MUL_flattened_Tnode - DESCRIPTION: - Prints the given tree as a MUL format alignment, with the sequences - in 'tree order' - RETURNS: - ARGS: - File handle - TNode * - NOTES: - *********************************************************************/ - -void write_MUL_flattened_Tnode( FILE *handle, struct Tnode *node) { - unsigned int i,j; - - if (node != NULL) { - write_MUL_flattened_Tnode( handle, node->left ); - if (node->clust != NULL) { - for( i=0; i < node->clust->clustersize; i++ ) { - fprintf( handle, "%-24s", node->clust->members[i]->name ); - for (j=0; j < node->clust->members[i]->length; j++) - fprintf( handle, "%c", node->clust->members[i]->seq[j] ); - fprintf( handle, "\n"); - } - } - write_MUL_flattened_Tnode( handle, node->right ); - } - -} - - - -/********************************************************************* - FUNCTION: write_MUL_flattened_Tree - DESCRIPTION: - Prints the given tree as a MUL format sequence alignment, with - the sequences in 'tree order' - RETURNS: - ARGS: - File handle - Tree * - NOTES: - *********************************************************************/ - -void write_MUL_flattened_Tree( FILE *handle, struct Tree *tr) { - if (tr != NULL) { - write_MUL_flattened_Tnode( handle, tr->child[0] ); - write_MUL_flattened_Tnode( handle, tr->child[1] ); - write_MUL_flattened_Tnode( handle, tr->child[2] ); - } - fflush( handle ); - -} - - - -/********************************************************************* - FUNCTION: write_newhampshire_Tnode - DESCRIPTION: - prints the given Tree in 'New Hampshire' text format to the given - file handle - RETURNS: - ARGS: - File handle - TNode * - Whether or not to show bootstrap values - NOTES: - *********************************************************************/ - -void write_newhampshire_Tnode( FILE *handle, struct Tnode *node, - unsigned int show_bootstraps ) { - if (node != NULL) { - /* We need to determine whether the node is a leaf or internal; - since in this implementation internal nodes do not have names, - it is sufficient to check the nodes name for nullness; however, - this precludes the possibilities of internal nodes being given - names in the future, hence the check for internalness is made - on the basis of the nullness of the children. - */ - - if ( node->left == NULL && node->right == NULL) { - /* this is a leaf node, so its cluster must have members; pain if not */ - if (node->clust->clustersize == 0 || node->clust->members == NULL) - fatal_util( "Fatal Error: encountered a leaf node with no cluster info"); - else if (node->clust->clustersize == 1) - fprintf( handle, "%s:%.5f", node->clust->members[0]->name, node->distance ); - else { - /* if there is more than one sequence belonging to the cluster, then this piece - of code will generate som internal nodes in the output tree with no bootstrap - values. Such is life... */ - unsigned int i; - - for (i=0; i < node->clust->clustersize - 1; i++) { - fprintf( handle, "(\n%s:%.5f,\n", node->clust->members[i]->name, 0.0 ); - } - fprintf( handle, "%s:%.5f)\n", node->clust->members[i]->name, 0.0); - for (i=0; i < node->clust->clustersize - 2; i++) { - fprintf( handle, ":%.5f)\n", 0.0 ); - } - - fprintf( handle, ":%.5f", node->distance); - /* fprintf( handle, "Cluster_%d:%.5f", node->nodenumber, node->distance ); */ - } - } - else if ( node->left != NULL && node->right != NULL ) { - fprintf( handle, "(\n"); - write_newhampshire_Tnode( handle, node->left, show_bootstraps ); - fprintf( handle, ",\n" ); - write_newhampshire_Tnode( handle, node->right, show_bootstraps ); - if (show_bootstraps) { - fprintf( handle, ")\n%d:%.5f", node->bootstrap, node->distance ); - } - else { - fprintf( handle, ")\n:%.5f", node->distance); - } - } - /* else do nothing */ - } - fflush( handle ); -} - - - -/********************************************************************* - FUNCTION: write_newhampshire_Tree - DESCRIPTION: - prints the given Tnode in 'New Hampshire' text format to the given - file handle - RETURNS: - ARGS: - File handle - TNode * - NOTES: - *********************************************************************/ - -void write_newhampshire_Tree( FILE *handle, struct Tree *thetree, - unsigned int show_bootstraps) { - - /* write_newhampshire_Tnode always places parenttheses around the - sub-tree if there is more than one sub-node, but this is not - appropriate if there there are no other sub-trees to draw at - this level. Hence there is a special case for a single - sub-tree (as returned by the UPGMA method) */ - - if (thetree != NULL) { - if (thetree->child[0] != NULL) { - if (thetree->child[1] == NULL) { - /* draw rooted tree */ - - if (thetree->child[0]->left != NULL && thetree->child[0]->right != NULL) { - fprintf( handle, "(\n"); - write_newhampshire_Tnode( handle, thetree->child[0]->left, show_bootstraps ); - fprintf( handle, ",\n"); - write_newhampshire_Tnode( handle, thetree->child[0]->right, show_bootstraps ); - fprintf( handle, ");\n"); - } - else { - /* this is a leaf node, and leaf nodes may contain a single sequence - or a cluser of sequences. If this leaf contains a single sequence, - then we have a tree of one sequence, in which case we print an - error, because trees of one sequence do not make sense */ - - if (thetree->child[0]->clust->clustersize == 1) - fatal_util( "Cannot build a tree with a single sequence %s", - thetree->child[0]->clust->members[0]->name); - else { - unsigned int i; - - for (i=0; i < thetree->child[0]->clust->clustersize - 1; i++) - fprintf( handle, "(\n%s:%.5f,\n", thetree->child[0]->clust->members[i]->name, 0.0 ); - - fprintf( handle, "%s:%.5f", thetree->child[0]->clust->members[i]->name, 0.0); - - for (i=0; i < thetree->child[0]->clust->clustersize - 2; i++) - fprintf( handle, ")\n:%.5f)\n", 0.0 ); - - fprintf( handle, ");\n"); - } - } - } - else { - fprintf( handle, "(\n"); - write_newhampshire_Tnode( handle, thetree->child[0], show_bootstraps ); - fprintf( handle, ",\n"); - write_newhampshire_Tnode( handle, thetree->child[1], show_bootstraps ); - if (thetree->child[2] != NULL) { - fprintf( handle, ",\n"); - write_newhampshire_Tnode( handle, thetree->child[2], show_bootstraps ); - } - fprintf( handle, ");\n"); - } - } - } - fflush( handle ); -} - - diff --git a/externalTools/quicktree_1.1/src/util.c b/externalTools/quicktree_1.1/src/util.c deleted file mode 100755 index 55ab203..0000000 --- a/externalTools/quicktree_1.1/src/util.c +++ /dev/null @@ -1,153 +0,0 @@ -/* Last edited: Feb 1 17:52 2002 (klh) */ -/********************************************************************** - ** FILE: util.c - ** NOTES: - ** This file contains general utiliy functions used throughout the - ** application, such as those for memory management and error - ** messaging. I have used it as a place to put other general stuff - ** until I have somewhere better to put it. - **********************************************************************/ - -#include "util.h" - - - -/********************************************************************* - FUNCTION: calloc_util - DESCRIPTION: - A wrapper for the stdlib.h function calloc; exits if memory cannot - be allocated - RETURNS: A generic pointer to the reallocated memory - ARGS: - The number of bytes to be allocated - NOTES: - *********************************************************************/ - -void *calloc_util( size_t numobjs, size_t size) { - void *ret; - - if ((ret = calloc( numobjs, size )) == NULL) - fatal_util("calloc_util: Out of memory"); - - return ret; -} - - - -/********************************************************************* - FUNCTION: malloc_util - DESCRIPTION: - A wrapper for the stdlib.h function malloc; exits if memory cannot - be allocated - RETURNS: A generic pointer to the reallocated memory - ARGS: - The number of bytes to be allocated - NOTES: - *********************************************************************/ - -void *malloc_util(size_t numbytes) { - void *ret; - - if ((ret = malloc( numbytes )) == NULL) - fatal_util("malloc_util: out of memory when requesting %d bytes", numbytes); - - return ret; -} - - - -/********************************************************************* - FUNCTION: realloc_util - DESCRIPTION: - A wrapper for the stdlib.h function realloc; exits if memory cannot - be allocated - RETURNS: A generic pointer to the reallocated memory - ARGS: - A pointer to the memory to be reallocated - The number of bytes to be allocated - NOTES: - *********************************************************************/ - -void *realloc_util(void *ptr, size_t bytes) { - void *ret = NULL; - - if (ptr == NULL) - fatal_util("Call to realloc_util with a null pointer"); - else { - if ((ret = realloc(ptr, bytes)) == NULL) - fatal_util("realloc_util: out of memory when requesting %d bytes", bytes); - } - - return ret; -} - - - -/********************************************************************* - FUNCTION: free_util - DESCRIPTION: - A wrapper for the stdlib.h function free; warns if the free could - not be performed - RETURNS: A (hopefully null) pointer - ARGS: - A pointer to the memory to be deallocated - NOTES: - *********************************************************************/ - -void *free_util( void *ptr ) { - if (ptr == NULL) - warning_util("Call to free_util with null pointer"); - else { - free(ptr); - ptr = NULL; - } - return ptr; -} - - - -/********************************************************************* - FUNCTION: fatal_util - DESCRIPTION: - Prints the given formatted error message and exits - RETURNS: - ARGS: - A format string + args, c.f. printf - NOTES: - *********************************************************************/ - -void fatal_util( char *fmt, ... ) { - va_list args; - - va_start( args, fmt ); - fprintf( stderr, "\nA Fatal Error occurred: "); - vfprintf( stderr, fmt, args); - fprintf( stderr,"\n"); - va_end( args ); - exit(1); -} - - - -/********************************************************************* - FUNCTION: warning_util - DESCRIPTION: - Prints the given formatted warning to stderr - RETURNS: - ARGS: - A format string + args, c.f. printf - NOTES: - *********************************************************************/ - -void warning_util( char *fmt, ...) { - va_list args; - - va_start( args, fmt ); - fprintf( stderr, "\nWARNING: " ); - vfprintf( stderr, fmt, args ); - fprintf( stderr, "\n" ); - va_end( args ); -} - - - diff --git a/include.mk b/include.mk deleted file mode 100644 index d536d07..0000000 --- a/include.mk +++ /dev/null @@ -1,123 +0,0 @@ -# we do specific stuff for specific host for now. -HOSTNAME = $(shell hostname) -MACH = $(shell uname -m) -SYS = $(shell uname -s) - -#C compiler. FIXME: for some reason the cxx variable is used, which -#typically means C++ compiler. -ifeq (${CC},cc) - ifeq (${SYS},FreeBSD) - # default FreeBSD gcc (4.2.1) has warning bug - #cxx = gcc46 -std=c99 -Wno-unused-but-set-variable - cxx = gcc34 -std=c99 -Wno-unused-but-set-variable - else ifeq ($(SYS),Darwin) #This is to deal with the Mavericks replacing gcc with clang fully - cxx = clang -std=c99 - else - cxx = gcc -std=c99 - endif -else - cxx = ${CC} -std=c99 -endif - -# C++ compiler. FIXME: for some reason the cpp variable is used, which -# typically refers to the C preprocessor. -ifndef CXX - ifeq (${SYS},FreeBSD) - # default FreeBSD gcc (4.2.1) has warning bug - cpp = g++ - else ifeq ($(SYS),Darwin) #This is to deal with the Mavericks replacing gcc with clang fully - cpp = clang++ - else - cpp = g++ - endif -else - cpp = ${CXX} -std=gnu++98 -endif - -# -Wno-unused-result - -# Compiler flags. -# DO NOT put static library -l options here. Those must be specified *after* -# linker input files. See . - -#Release compiler flags -cflags_opt = -O3 -g -Wall --pedantic -funroll-loops -DNDEBUG -#-fopenmp -cppflags_opt = -O3 -g -Wall -funroll-loops -DNDEBUG - -#Debug flags (slow) -cflags_dbg = -Wall -O0 -Werror --pedantic -g -fno-inline -UNDEBUG -Wno-error=unused-result -cppflags_dbg = -Wall -g -O0 -fno-inline -UNDEBUG - -#Ultra Debug flags (really slow, checks for memory issues) -cflags_ultraDbg = -Wall -Werror --pedantic -g -O1 -fno-inline -fno-omit-frame-pointer -fsanitize=address -cppflags_ultraDbg = -g -O1 -fno-inline -fno-omit-frame-pointer -fsanitize=address - -#Profile flags -cflags_prof = -Wall -Werror --pedantic -pg -O3 -g -Wno-error=unused-result - -#Flags to use -ifndef CGL_DEBUG - cppflags = ${cppflags_opt} - cflags = ${cflags_opt} -else - ifeq (${CGL_DEBUG},ultra) - cppflags = ${cppflags_ultraDbg} - cflags = ${cflags_ultraDbg} - else - cppflags = ${cppflags_dbg} - cflags = ${cflags_dbg} - endif -endif -# location of Tokyo cabinet -ifndef tokyoCabinetLib -ifneq ($(wildcard /hive/groups/recon/local/include/tcbdb.h),) - # hgwdev hive install - tcPrefix = /hive/groups/recon/local - tokyoCabinetIncl = -I${tcPrefix}/include -DHAVE_TOKYO_CABINET=1 - tokyoCabinetLib = -L${tcPrefix}/lib -Wl,-rpath,${tcPrefix}/lib -ltokyocabinet -lz -lbz2 -lpthread -lm -else ifneq ($(wildcard /opt/local/include/tcbdb.h),) - # OS/X with TC installed from MacPorts - tcPrefix = /opt/local - tokyoCabinetIncl = -I${tcPrefix}/include -DHAVE_TOKYO_CABINET=1 - tokyoCabinetLib = -L${tcPrefix}/lib -Wl,-rpath,${tcPrefix}/lib -ltokyocabinet -lz -lbz2 -lpthread -lm -else ifneq ($(wildcard /usr/local/include/tcbdb.h),) - # /usr/local install (FreeBSD, etc) - tcPrefix = /usr/local - tokyoCabinetIncl = -I${tcPrefix}/include -DHAVE_TOKYO_CABINET=1 - tokyoCabinetLib = -L${tcPrefix}/lib -Wl,-rpath,${tcPrefix}/lib -ltokyocabinet -lz -lbz2 -lpthread -lm -else ifneq ($(wildcard /usr/include/tcbdb.h),) - # /usr install (Ubuntu, and probably most Debain-based systems) - tcPrefix = /usr - tokyoCabinetIncl = -I${tcPrefix}/include -DHAVE_TOKYO_CABINET=1 - tokyoCabinetLib = -L${tcPrefix}/lib -Wl,-rpath,${tcPrefix}/lib -ltokyocabinet -lz -lbz2 -lpthread -lm -endif -endif - -# location of Kyoto Tycoon -ifndef kyotoTycoonLib -ifneq ($(wildcard /hive/groups/recon/local/include/ktcommon.h),) - # hgwdev hive install - ttPrefix = /hive/groups/recon/local - kyotoTycoonIncl = -I${ttPrefix}/include -DHAVE_KYOTO_TYCOON=1 - kyotoTycoonLib = -L${ttPrefix}/lib -Wl,-rpath,${ttPrefix}/lib -lkyototycoon -lkyotocabinet -lz -lbz2 -lpthread -lm -lstdc++ -else ifneq ($(wildcard /opt/local/include/ktcommon.h),) - # OS/X with TC installed from MacPorts - ttPrefix = /opt/local - kyotoTycoonIncl = -I${ttPrefix}/include -DHAVE_KYOTO_TYCOON=1 - kyotoTycoonLib = -L${ttPrefix}/lib -Wl,-rpath,${ttPrefix}/lib -lkyototycoon -lkyotocabinet -lz -lbz2 -lpthread -lm -lstdc++ -else ifneq ($(wildcard /usr/local/include/ktcommon.h),) - # /usr/local install (FreeBSD, etc) - ttPrefix = /usr/local - kyotoTycoonIncl = -I${ttPrefix}/include -DHAVE_KYOTO_TYCOON=1 - kyotoTycoonLib = -L${ttPrefix}/lib -Wl,-rpath,${ttPrefix}/lib -lkyototycoon -lkyotocabinet -lz -lbz2 -lpthread -lm -lstdc++ -else ifneq ($(wildcard /usr/include/ktcommon.h),) - # /usr install (Ubuntu) - ttPrefix = /usr - kyotoTycoonIncl = -I${ttPrefix}/include -DHAVE_KYOTO_TYCOON=1 - kyotoTycoonLib = -L${ttPrefix}/lib -Wl,-rpath,${ttPrefix}/lib -lkyototycoon -lkyotocabinet -lz -lbz2 -lpthread -lm -lstdc++ -endif -endif - -dblibs = ${tokyoCabinetLib} ${kyotoTycoonLib} -lz -lm - diff --git a/kvdbTest.py b/kvdbTest.py deleted file mode 100644 index ae0de1d..0000000 --- a/kvdbTest.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt - -import unittest - -import os -import sys -import socket - -from sonLib.bioio import system - -class TestCase(unittest.TestCase): - - def testSonLibKVTokyoCabinet(self): - system("sonLib_kvDatabaseTest --type=tokyocabinet") - - def testSonLibKVKyotoTycoon(self): - #Needs a ktserver process running on the local machine, we need to add a check for this condition to stop the test failing - return #Disabled for now - system("sonLib_kvDatabaseTest --type=kyototycoon --host=localhost --port=1978 --maxKTRecordSize=6500000") - - def testSonLibKVMySQLTest(self): - return - if socket.gethostname() == "hgwdev": - system("sonLib_kvDatabaseTest --type=mysql --host=kolossus-10 --user=cactus --pass=cactus --db=cactus") - -if __name__ == '__main__': - unittest.main() diff --git a/misc.py b/misc.py deleted file mode 100644 index 4c3af55..0000000 --- a/misc.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt - -import sys -import os -import re -import math - -######################################################### -######################################################### -######################################################### -#misc functions -######################################################### -######################################################### -######################################################### - -def sonTraceRootPath(): - """ - function for finding external location - """ - import sonLib.bioio - i = os.path.abspath(sonLib.bioio.__file__) - return os.path.split(os.path.split(os.path.split(i)[0])[0])[0] - -def linOriginRegression(points): - """ - computes a linear regression starting at zero - """ - j = sum([ i[0] for i in points ]) - k = sum([ i[1] for i in points ]) - if j != 0: - return k/j, j, k - return 1, j, k - -def close(i, j, tolerance): - """ - check two float values are within a bound of one another - """ - return i <= j + tolerance and i >= j - tolerance - -def getPositiveCoordinateRangeOverlap(uStart1, uEnd1, uStart2, uEnd2): - """@return: If the two coordinate ranges overlap on the same strand - returns the overlap range. If no overlap it returns None. - """ - if uEnd1 < uStart2 or uEnd2 < uStart1: - return None - l = [ uStart1, uEnd1, uStart2, uEnd2 ] - l.sort() - return l[1], l[2] - -def getCoordinateRangeOverlap(uStart1, uEnd1, uStart2, uEnd2): - """@return: If the two coordinate ranges overlap (even on opposite strands) - returns the overlap, on the same strand as the first range of coordinates. - If no overlap it returns None. - """ - #deal with negative strands - if uStart1 <= 0: - if uStart2 <= 0: - rangeOverlap = getPositiveCoordinateRangeOverlap(-uEnd1, -uStart1, - -uEnd2, -uStart2) - else: - rangeOverlap = getPositiveCoordinateRangeOverlap(-uEnd1, -uStart1, - uStart2, uEnd2) - if rangeOverlap is not None: - x, y = rangeOverlap - return -y, -x - return None - if uStart2 <=0: - return getPositiveCoordinateRangeOverlap(uStart1, uEnd1, - -uEnd2, -uStart2) - return getPositiveCoordinateRangeOverlap(uStart1, uEnd1, uStart2, uEnd2) - -def sortAlignments(alignments): - def cmpFn(a1, a2): #Sort in descending order - if a1.score > a2.score: - return 1 - elif a1.score < a2.score: - return -1 - return 0 - alignments.sort(cmpFn) - return alignments - -def filterOverlappingAlignments(alignments): - """Filter alignments to be non-overlapping. - """ - l = [] - alignments = alignments[:] - sortAlignments(alignments) - alignments.reverse() - for pA1 in alignments: - for pA2 in l: - if pA1.contig1 == pA2.contig1 and getPositiveCoordinateRangeOverlap(pA1.start1+1, pA1.end1, pA2.start1+1, pA2.end1) is not None: #One offset, inclusive coordinates - break - if pA1.contig2 == pA2.contig2 and getPositiveCoordinateRangeOverlap(pA1.start2+1, pA1.end2, pA2.start2+1, pA2.end2) is not None: #One offset, inclusive coordinates - break - if pA1.contig2 == pA2.contig1 and getPositiveCoordinateRangeOverlap(pA1.start2+1, pA1.end2, pA2.start1+1, pA2.end1) is not None: #One offset, inclusive coordinates - break - if pA1.contig1 == pA2.contig2 and getPositiveCoordinateRangeOverlap(pA1.start1+1, pA1.end1, pA2.start2+1, pA2.end2) is not None: #One offset, inclusive coordinates - break - else: - l.append(pA1) - l.reverse() - return l - -######################################################### -######################################################### -######################################################### -#continuous math functions -######################################################### -######################################################### -######################################################### - -LOG_ZERO_PROB = -1e30000 -LOG_ONE_PROB = 0.0 -ZERO_PROB = 0.0 - -def logAdd(x, y): - if x < y: - if x <= LOG_ZERO_PROB: - return y - return math.log(math.exp(x - y) + 1) + y - if y <= LOG_ZERO_PROB: - return x - return math.log(math.exp(y - x) + 1) + x - -######################################################### -######################################################### -######################################################### -#bio functions -######################################################### -######################################################### -######################################################### - -dNAMap_reverseComp_IUPAC = { 'A':'T', 'C':'G', 'G':'C', 'T':'A', 'a':'t', 'c':'g', 'g':'c', 't':'a', 'N':'N', 'n':'n' } - -dNAMap_reverseComp_Int = { 0:3, 1:2, 2:1, 3:0, 4:4 } - -def reverseComplement(seq, rCM=dNAMap_reverseComp_Int): - seq.reverse() - i = [ rCM[j] for j in seq ] - seq.reverse() - return i - -def main(): - pass - -def _test(): - import doctest - return doctest.testmod() - -if __name__ == '__main__': - _test() - main() diff --git a/nxnewick.py b/nxnewick.py deleted file mode 100644 index 65223dc..0000000 --- a/nxnewick.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Glenn Hickey -# -#Released under the MIT license, see LICENSE.txt -#!/usr/bin/env python - -"""read and write newick trees to and from networkx graphs (as wrapped by nxtree). -""" -import sys -import os -import re -import math -import random -from string import whitespace as ws -from sonLib.misc import close -import bioio -import networkx as NX -from optparse import OptionParser -from sonLib.nxtree import NXTree - - -class NXNewick(object): - def __init__(self, nxTree = None): - self.nxTree = None - self.bracketMatch = None - self.inString = None - self.nextId = 0 - self.outString = None - - def parseFile(self, path): - inFile = open(path) - self.parseString(inFile.read()) - inFile.close() - return self.nxTree - - def parseString(self, newickString, addImpliedRoots = True): - self.nxTree = NXTree() - self.inString = self.__filterWhitespace(newickString) - self.__createBracketTable() - self.nextId = 0 - assert self.inString[-1] == ';' - self.__addNode(0, len(self.inString)-1, None, addImpliedRoots) - self.nxTree.isTree() - return self.nxTree - - def writeString(self, nxTree = None): - if nxTree: - self.nxTree = nxTree - self.outString = "" - self.__writeNode(self.nxTree.getRootId(), None) - self.outString += ";" - return self.outString - - def writeFile(self, path, nxTree = None): - outFile = open(path, "w") - outFile.write(self.writeString(nxTree)) - outFile.write("\n") - outFile.close() - return None - - #### PRIVATE WRITING FUNCTIONS #### - def __writeNode(self, node, parent = None): - children = self.nxTree.getChildren(node) - if len(children) > 0: - self.outString += "(" - for child in children: - self.__writeNode(child, node) - if child != children[-1]: - self.outString += "," - if len(children) > 0: - self.outString += ")" - name = self.nxTree.getName(node) - - if len(name) > 0: - containsSpace = True in [c1 in name for c1 in ws] - if containsSpace: - self.outString += "\"" - self.outString += name - if containsSpace: - self.outString += "\"" - if parent is not None: - weight = self.nxTree.getWeight(parent, node, defaultValue=None) - if weight is not None: - self.outString += ":%s" % str(weight) - - #### PRIVATE READING FUNCTIONS #### - - def __filterWhitespace(self, newickString): - filteredString = "" - inQuote = False - for c in newickString: - if c == "\'" or c == "\"": - inQuote = not inQuote - elif inQuote or c not in ws: - filteredString += c - return filteredString - - def __createBracketTable(self): - bracketStack = [] - self.bracketMatch = dict() - index = 0 - for c in self.inString: - if c == '(': - bracketStack.append(index) - elif c == ')': - leftIndex = bracketStack.pop() - self.bracketMatch[leftIndex] = index - index += 1 - assert len(bracketStack) == 0 - - def __childRanges(self, start, length): - ranges = [] - currentStart = start - i = currentStart - while i < start + length + 1: - if self.inString[i] == ',' or i == start + length: - ranges.append((currentStart, i - currentStart)) - currentStart = i + 1 - if i in self.bracketMatch: - i = self.bracketMatch[i] - i += 1 - return ranges - - def __parseName(self, nameString): - if nameString == ';': - return ('','') - tokens = nameString.split(':') - assert len(tokens) == 1 or len(tokens) == 2 - name = tokens[0] - weight = '' - if len(tokens) == 2: - weight = tokens[1] - return (name, weight) - - def __addNode(self, start, length, parent = None, addImpliedRoots = True): - # parse the children (..,...,..) - children = [] - if self.inString[start] == '(': - assert start in self.bracketMatch - chLength = self.bracketMatch[start] - start - 1 - children = self.__childRanges(start+1, chLength) - start = self.bracketMatch[start] + 1 - length -= (chLength + 2) - - # prase the name abc:123 - name, weight = self.__parseName(self.inString[start:start+length]) - id = self.nextId - self.nextId += 1 - self.nxTree.nxDg.add_node(id) - if len(name) > 0: - self.nxTree.nxDg.node[id]['name'] = name - - #update the graph - if parent is not None: - self.nxTree.nxDg.add_edge(parent, id) - if len(weight) > 0: - self.nxTree.nxDg[parent][id]['weight'] = float(weight) - - #update the root (implied roots are added as a new node) - if self.nxTree.getRootId() is None: - assert parent is None - root = id - if len(weight) > 0: - if addImpliedRoots: - root = self.nextId - self.nextId += 1 - self.nxTree.nxDg.add_edge(root, id) - self.nxTree.setWeight(root,id, weight) - self.nxTree.rootId = root - - # recurse on children - for child in children: - self.__addNode(child[0], child[1], id) - -def main(): - usage = "usage: %prog " - description = "TEST: convert newick tree to graphviz tree" - parser = OptionParser(usage=usage, description=description) - options, args = parser.parse_args() - - if len(args) != 3: - parser.print_help() - raise RuntimeError("Wrong number of arguments") - - parser = NXNewick() - parser.parseFile(args[0]) - NX.drawing.nx_agraph.write_dot(parser.nxTree.nxDg, args[1]) - parser.writeFile(args[2]) - print "PRE" - for i in parser.nxTree.preOrderTraversal(): - print ("%d %s" % (i, parser.nxTree.getName(i))) - print "POST" - for i in parser.nxTree.postOrderTraversal(): - print ("%d %s" % (i, parser.nxTree.getName(i))) - print "BFS" - for i in parser.nxTree.breadthFirstTraversal(): - print ("%d %s" % (i, parser.nxTree.getName(i))) - return 0 - -if __name__ == '__main__': - main() diff --git a/nxnewickTest.py b/nxnewickTest.py deleted file mode 100644 index b38bd25..0000000 --- a/nxnewickTest.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 011 by Glenn Hickey -# -#Released under the MIT license, see LICENSE.txt - -import unittest -import random -import re -from string import whitespace as ws - -from sonLib.nxnewick import NXNewick -from sonLib.bioio import TestStatus -from sonLib.bioio import logger - -class TestCase(unittest.TestCase): - - def setUp(self): - self.testNo = TestStatus.getTestSetup() - unittest.TestCase.setUp(self) - - def tearDown(self): - unittest.TestCase.tearDown(self) - - def testNewickIO(self): - # feslenstein's own... (http://evolution.genetics.washington.edu/phylip/newicktree.html) - tree1 = '((raccoon:19.19959,bear:6.80041):0.846,((sea_lion:11.997, seal:12.003):7.52973,((monkey:100.8593,cat:47.14069):20.59201, weasel:18.87953):2.0946):3.87382,dog:25.46154);' - tree2 = '(Bovine:0.69395,(Gibbon:0.36079,(Orang:0.33636,(Gorilla:0.17147,(Chimp:0.19268, Human:0.11927):0.08386):0.06124):0.15057):0.54939,Mouse:1.2146):0.1;' - tree3 = '(Bovine:0.69395,(Hylobates:0.36079,(Pongo:0.33636,(G._Gorilla:0.17147, (P._paniscus:0.19268,H._sapiens:0.11927):0.08386):0.06124):0.15057):0.54939, Rodent:1.2146);' - tree4 = 'A;' - tree5 = '((A,B):0.0,(C,D));' - tree6 = '(Alpha,Beta,Gamma,Delta,,Epsilon,,,);' - - trees = [tree1, tree2, tree3, tree4, tree5, tree6] - newickParser = NXNewick() - - # Parse newicks, adding implied roots - for tree in trees: - newickParser.parseString(tree, addImpliedRoots=True) - answer = self.__cleanTree(tree) - outputString = newickParser.writeString() - logger.debug(" ***************** ") - logger.debug(outputString) - logger.debug(answer) - assert outputString == answer - - # Parse newicks, not adding implied roots - for tree in trees: - newickParser.parseString(tree, addImpliedRoots=False) - outputString = newickParser.writeString() - answer = re.sub(r':[.0-9]+?;', ';', tree) - answer = re.sub(r'\s+', '', answer) - logger.debug(" ***************** ") - logger.debug(outputString) - logger.debug(answer) - assert outputString == answer - - - # remove whitespace - # change trees of form (blabla):123; to ((blabla):123); - def __cleanTree(self, tree): - result = "" - for c in tree: - if c not in ws: - result += c - if result[len(result) -2 ] != ')' and result[0] == '(': - result = "(%s);" % result[:len(result) - 1] - return result - -if __name__ == '__main__': - unittest.main() diff --git a/nxtree.py b/nxtree.py deleted file mode 100644 index 3fe82b8..0000000 --- a/nxtree.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Glenn Hickey -# -#Released under the MIT license, see LICENSE.txt -#!/usr/bin/env python - -"""A more general (ie arbitrary degree) tree to replace the BinaryTree -in sonLib.tree.py. Implemented as a lightweight wrapper over a -networkx digraph. nodes are accessed using unique ids. - -for now, there is no interface (beyond directly working the -networkx graph or reading from newick) to modify the structure of the tree. -update -- added function to remove leaves (and their parents if deg. 2) -""" -import sys -import os -import networkx as NX -from optparse import OptionParser - -class NXTree(object): - def __init__(self, nxDg = None): - self.nxDg = nxDg - if self.nxDg is None: - self.nxDg = NX.DiGraph() - self.isTree() - self.rootId = None - self.computeRootId() - - def isTree(self): - assert NX.is_directed_acyclic_graph(self.nxDg) - for node in self.nxDg.nodes(): - assert len(self.nxDg.in_edges(node)) < 2 - - def computeRootId(self): - self.rootId = None - for node in self.nxDg.nodes(): - if len(self.nxDg.in_edges(node)) == 0: - self.rootId = node - break - - def loadNetworkXTree(self, nxDg): - self.nxDg = nxDg - self.isTree() - self.computeRootId() - - def getChildren(self, id): - assert id in self.nxDg - return sorted([x[1] for x in self.nxDg.out_edges(id)]) - - def isLeaf(self, id): - return len(self.getChildren(id)) == 0 - - def getLeaves(self): - leaves = [] - for i in self.breadthFirstTraversal(): - if self.isLeaf(i): - leaves.append(i) - return leaves - - def hasParent(self, id): - return self.getParent(id) is not None - - def getParent(self, id): - assert id in self.nxDg - edges = self.nxDg.in_edges(id) - assert len(edges) < 2 - if len(edges) == 0: - return None - else: - return edges[0][0] - - def getName(self, id): - assert id in self.nxDg - node = self.nxDg.node[id] - if 'name' in node: - return node['name'] - return "" - - def setName(self, id, name): - assert id in self.nxDg - self.nxDg.node[id]['name'] = name - - def hasName(self, id): - assert id in self.nxDg - node = self.nxDg.node[id] - return 'name' in node - - def getWeight(self, parentId, childId, defaultValue=None): - assert parentId in self.nxDg and childId in self.nxDg - edge = self.nxDg[parentId][childId] - if 'weight' in edge: - return edge['weight'] - return defaultValue - - def setWeight(self, parentId, childId, weight): - assert parentId in self.nxDg and childId in self.nxDg - self.nxDg[parentId][childId]['weight'] = float(weight) - - def getRootId(self): - return self.rootId - - def getRootName(self): - return self.getName(self.getRootId()) - - def preOrderTraversal(self, root = None): - if root is None: - root = self.rootId - yield root - for child in self.getChildren(root): - for node in self.preOrderTraversal(child): - yield node - - def postOrderTraversal(self, root = None): - if root is None: - root = self.rootId - for child in self.getChildren(root): - for node in self.postOrderTraversal(child): - yield node - yield root - - def breadthFirstTraversal(self, root = None): - if root is None: - root = self.rootId - bfQueue = [root] - while len(bfQueue) > 0: - node = bfQueue.pop(0) - yield node - for child in self.getChildren(node): - bfQueue.append(child) - - def removeDegree2Vertex(self, nodeId): - if self.hasParent(nodeId) is True: - parentId = self.getParent(nodeId) - topWeight = self.getWeight(parentId, nodeId) - children = self.getChildren(nodeId) - if len(children) == 1: - childId = children[0] - botWeight = self.getWeight(nodeId, childId) - if topWeight is None and botWeight is None: - newWeight = None - elif topWeight is None: - newWeight = botWeight - elif botWeight is None: - newWeight = topWeight - else: - newWeight = topWeight + botWeight - self.nxDg.remove_node(nodeId) - self.nxDg.add_edge(parentId, childId) - self.nxDg[parentId][childId]['weight'] = float(newWeight) - - def removeLeaf(self, leafId): - assert self.isLeaf(leafId) - parentId = self.getParent(leafId) - self.nxDg.remove_node(leafId) - if len(self.getChildren(parentId)) == 1 and \ - self.hasParent(parentId) is True: - self.removeDegree2Vertex(parentId) - - def removeEdge(self, parentId, childId): - self.nxDg.remove_edge(parentId, childId) - - def reroot(self, newRootId): - flipEdges = [] - node = newRootId - while self.hasParent(node) is True: - parent = self.getParent(node) - flipEdges.append((parent, node)) - node = parent - for edge in flipEdges: - self.nxDg.add_edge(edge[1], edge[0]) - self.nxDg[edge[1]][edge[0]] = self.nxDg[edge[0]][edge[1]] - self.nxDg.remove_edge(edge[0], edge[1]) - self.rootId = newRootId - - - - - - - - - - - diff --git a/nxtreeTest.py b/nxtreeTest.py deleted file mode 100644 index d7600c1..0000000 --- a/nxtreeTest.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 011 by Glenn Hickey -# -#Released under the MIT license, see LICENSE.txt - -import unittest -import random -import copy - -import networkx as NX -from sonLib.nxtree import NXTree -from sonLib.bioio import TestStatus - -class TestCase(unittest.TestCase): - - def setUp(self): - self.testNo = TestStatus.getTestSetup() - unittest.TestCase.setUp(self) - self.trees = randomTreeSet() - - def tearDown(self): - unittest.TestCase.tearDown(self) - - def testRoot(self): - for tree in self.trees: - nxTree = NXTree(tree) - rootId = nxTree.getRootId() - assert rootId is not None - assert nxTree.getParent(rootId) is None - - def testTraversals(self): - for tree in self.trees: - nxTree = NXTree(tree) - dfs = [x for x in nxTree.preOrderTraversal()] - assert len(set(dfs)) == len(nxTree.nxDg.nodes()) - dfs = [x for x in nxTree.postOrderTraversal()] - assert len(set(dfs)) == len(nxTree.nxDg.nodes()) - bfs = [x for x in nxTree.breadthFirstTraversal()] - assert len(set(bfs)) == len(nxTree.nxDg.nodes()) - - def testReroot(self): - tree = NX.DiGraph() - edges = [(1,2), (1,3), (2,4), (2,5), (5,6), (5,7), (5,8)] - for edge in edges: - tree.add_edge(edge[0], edge[1]) - nxTree = NXTree(tree) - nxTree.setWeight(1, 2, 3.1) - to = [x for x in nxTree.breadthFirstTraversal()] - - testTree = copy.deepcopy(nxTree) - testTree.reroot(1) - t = [x for x in testTree.breadthFirstTraversal()] - assert t == to - - testTree = copy.deepcopy(nxTree) - testTree.reroot(2) - t = [x for x in testTree.breadthFirstTraversal()] - assert t[0] == 2 - assert sorted(t[1:4]) == [1,4,5] - assert sorted(t[4:]) == [3,6,7,8] - assert testTree.getWeight(2, 1) == 3.1 - - testTree = copy.deepcopy(nxTree) - testTree.reroot(7) - t = [x for x in testTree.breadthFirstTraversal()] - assert t[0] == 7 - assert t[1] == 5 - assert sorted(t[2:5]) == [2,6,8] - assert sorted(t[5:7]) == [1,4] - assert t[7] == 3 - - -def randomTreeSet(): - trees = [] - for height in [1, 3, 6]: - for degree in [1,2,3,4,5]: - tree = NX.generators.classic.balanced_tree(degree, height) - trees.append(makeDirected(tree)) - for n in [20, 50, 100, 200, 500, 1000]: - tree = NX.generators.random_graphs.random_powerlaw_tree(n, - tries=90000) - trees.append(makeDirected(tree)) - return trees - -def makeDirected(tree): - root = None - for node in tree.nodes(): - if tree.degree(node) == 1: - root = node - break - assert root is not None - dtree = NX.DiGraph(tree) - bfq = [root] - while len(bfq) > 0: - node = bfq.pop() - for edge in dtree.out_edges(node): - dtree.remove_edge(edge[1], node) - bfq.append(edge[1]) - return dtree - -if __name__ == '__main__': - unittest.main() diff --git a/setup.py b/setup.py deleted file mode 100755 index 17503b2..0000000 --- a/setup.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python - -from setuptools import setup -import subprocess -import distutils.command.build_py - -class BuildWithMake(distutils.command.build_py.build_py): - """ - Build using make. - Then do the default build logic. - - """ - def run(self): - # Call make. - subprocess.check_call(["make"]) - - # Keep building the Python stuff - distutils.command.build_py.build_py.run(self) - - -setup(name="sonLib", - version="1.0", - description="Small general purpose library for C and Python with focus on " - "bioinformatics.", - author="Benedict Paten", - author_email="benedict@soe.ucsc.edu", - url="https://github.com/benedictpaten/sonLib", - packages=["sonLib"], - # Hook the build command to also build with make - cmdclass={"build_py": BuildWithMake}, - # Install all the executable scripts and binaries somewhere on the PATH - scripts=["bin/sonLibTests", "bin/sonLib_daemonize.py", - "bin/sonLib_kvDatabaseTest", "bin/sonLib_cigarTest", - "bin/sonLib_fastaCTest"]) - - diff --git a/sonLib_daemonize.py b/sonLib_daemonize.py deleted file mode 100644 index 9e146e0..0000000 --- a/sonLib_daemonize.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python - -# Glenn Hickey 2011 -# -#Released under the MIT license, see LICENSE.txt -""" -launch a command as a daemon. - -mostly copied from (and see for comments & explanation): - -######################################################################## -Copyright (C) 2005 Chad J. Schroeder -http://code.activestate.com/recipes/278731/ - -Disk And Execution MONitor (Daemon) - -Configurable daemon behaviors: - - 1.) The current working directory set to the "/" directory. - 2.) The current file creation mode mask set to 0. - 3.) Close all open files (1024). - 4.) Redirect standard I/O streams to "/dev/null". - -A failed call to fork() now raises an exception. - -References: - 1) Advanced Programming in the Unix Environment: W. Richard Stevens - 2) Unix Programming Frequently Asked Questions: - http://www.erlenstar.demon.co.uk/unix/faq_toc.html -######################################################################## - -handy to break out of a jobTree dependence (which the regular -os.system and subprocess.Popen can't do on their own) - -takes single argument: the command line to execute -be careful: the command line is not executed in a shell - -example: sonLib_daemonize.py 'ktserver -port 26' - -""" - -import os -import sys -import resource -import signal -import subprocess -from sonLib.bioio import system - -# Default daemon parameters. -# File mode creation mask of the daemon. -# use sonLib.bioio.spawnDaemon() for a python interface - -UMASK = 0 - -# Default working directory for the daemon. -WORKDIR = "/" - -# Default maximum for the number of available file descriptors. -MAXFD = 1024 - -# The standard I/O file descriptors are redirected to /dev/null by default. -if (hasattr(os, "devnull")): - REDIRECT_TO = os.devnull -else: - REDIRECT_TO = "/dev/null" - -if __name__ == '__main__': - if len(sys.argv) != 2: - raise Exception, "%s: Wrong number of arguments" % sys.argv[0] - - pid = os.fork() - if pid > 0: - os._exit(0) - - os.chdir("/") - os.setsid() - - signal.signal(signal.SIGHUP, signal.SIG_IGN) - os.umask(0) - pid = os.fork() - if pid > 0: - os._exit(0) - - maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] - if (maxfd == resource.RLIM_INFINITY): - maxfd = MAXFD - - # Iterate through and close all file descriptors. - for fd in range(0, maxfd): - try: - os.close(fd) - except OSError: # ERROR, fd wasn't open to begin with (ignored) - pass - - # Redirect the standard I/O file descriptors to the specified file. Since - os.open(REDIRECT_TO, os.O_RDWR) # standard input (0) - - # Duplicate standard input to standard output and standard error. - os.dup2(0, 1) # standard output (1) - os.dup2(0, 2) # standard error (2) - - retVal = subprocess.call(sys.argv[1].split(), shell=False, bufsize=-1) - sys.exit(retVal) diff --git a/tree.py b/tree.py deleted file mode 100644 index 0818c8c..0000000 --- a/tree.py +++ /dev/null @@ -1,792 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt - -import sys -import os -import re -import math -import random - -from sonLib.misc import close -#import bioio - -######################################################### -######################################################### -######################################################### -#basic tree datastructures -######################################################### -######################################################### -######################################################### - -MIN_TREE_DISTANCE = 0.00001 - -class BinaryTree: - def __init__(self, distance, internal, left, right, iD): - self.distance = distance - self.internal = internal - self.left = left - self.right = right - self.iD = iD - -class TraversalID: - """ - tree traversal numbers, used as nodeIDs for identifying - orders in the tree - """ - def __init__(self, midStart, mid, midEnd): - self.midStart = midStart - self.mid = mid - self.midEnd = midEnd - -######################################################### -######################################################### -######################################################### -#tree functions -######################################################### -######################################################### -######################################################### - -def binaryTree_depthFirstNumbers(binaryTree, labelTree=True, dontStopAtID=True): - """ - get mid-order depth first tree numbers - """ - traversalIDs = {} - def traverse(binaryTree, mid=0, leafNo=0): - if binaryTree.internal and (dontStopAtID or binaryTree.iD is None): - midStart = mid - j, leafNo = traverse(binaryTree.left, mid, leafNo) - mid = j - j, leafNo = traverse(binaryTree.right, j+1, leafNo) - traversalIDs[binaryTree] = TraversalID(midStart, mid, j) - return j, leafNo - traversalID = TraversalID(mid, mid, mid+1) - traversalID.leafNo = leafNo - #thus nodes must be unique - traversalIDs[binaryTree] = traversalID - return mid+1, leafNo+1 - traverse(binaryTree) - if labelTree: - for binaryTree in traversalIDs.keys(): - binaryTree.traversalID = traversalIDs[binaryTree] - return traversalIDs - -def binaryTree_nodeNames(binaryTree): - """ - creates names for the leave and internal nodes - of the newick tree from the leaf labels - """ - def fn(binaryTree, labels): - if binaryTree.internal: - fn(binaryTree.left, labels) - fn(binaryTree.right, labels) - labels[binaryTree.traversalID.mid] = labels[binaryTree.left.traversalID.mid] + "_" + labels[binaryTree.right.traversalID.mid] - return labels[binaryTree.traversalID.mid] - else: - labels[binaryTree.traversalID.mid] = str(binaryTree.iD) - return labels[binaryTree.traversalID.mid] - labels = [None]*binaryTree.traversalID.midEnd - fn(binaryTree, labels) - return labels - -def getBinaryTreeNodes(binaryTree, l): - if binaryTree is not None: - getBinaryTreeNodes(binaryTree.left, l) - l.append(binaryTree) - getBinaryTreeNodes(binaryTree.right, l) - -def binaryTree_leafNo(binaryTree): - return (binaryTree.traversalID.midEnd - binaryTree.traversalID.midStart + 1)/2 - -def getDistanceMatrix(tree): - m = {} - def fn(tree): - if tree.internal: - leftNodes = fn(tree.left) - rightNodes = fn(tree.right) - for i, d1 in leftNodes: - for j, d2 in rightNodes: - m[(i, j)] = d1 + d2 - m[(j, i)] = d1 + d2 - j = tree.traversalID.mid - for i, d1 in leftNodes + rightNodes: - m[(i, j)] = d1 - m[(j, i)] = d1 - return [ (i[0], i[1]+tree.distance) for i in leftNodes + rightNodes + [(j, 0.0)] ] - return [ (tree.traversalID.mid, tree.distance) ] - fn(tree) - return m - - -def makeRandomBinaryTree(leafNodeNumber=None): - """Creates a random binary tree. - """ - while True: - nodeNo = [-1] - def fn(): - nodeNo[0] += 1 - if random.random() > 0.6: - i = str(nodeNo[0]) - return BinaryTree(0.00001 + random.random()*0.8, True, fn(), fn(), i) - else: - return BinaryTree(0.00001 + random.random()*0.8, False, None, None, str(nodeNo[0])) - tree = fn() - def fn2(tree): - if tree.internal: - return fn2(tree.left) + fn2(tree.right) - return 1 - if leafNodeNumber is None or fn2(tree) == leafNodeNumber: - return tree - -def getRandomBinaryTreeLeafNode(binaryTree): - """Get random binary tree node. - """ - if binaryTree.internal == True: - if random.random() > 0.5: - return getRandomBinaryTreeLeafNode(binaryTree.left) - else: - return getRandomBinaryTreeLeafNode(binaryTree.right) - else: - return binaryTree - -######################################################### -######################################################### -######################################################### -#substition functions and felsensteins algorithm -######################################################### -######################################################### -######################################################### - -def transformByDistance(wV, subModel, alphabetSize=4): - """ - transform wV by given substitution matrix - """ - nc = [0.0]*alphabetSize - for i in xrange(0, alphabetSize): - j = wV[i] - k = subModel[i] - for l in xrange(0, alphabetSize): - nc[l] += j * k[l] - return nc - -def multiplyWV(wVX, wVY, alphabetSize=4): - return [ wVX[i] * wVY[i] for i in xrange(0, alphabetSize) ] - -def sumWV(wVX, wVY, alphabetSize=4): - return [ wVX[i] + wVY[i] for i in xrange(0, alphabetSize) ] - -def normaliseWV(wV, normFac=1.0): - """ - make char probs divisible by one - """ - f = sum(wV) / normFac - return [ i/f for i in wV ] - -def sumWVA(wVA, alphabetSize=4): - totals = [0.0]*alphabetSize - for wV in wVA: - for i in xrange(0, alphabetSize): - totals[i] += wV[i] - return totals - -def felsensteins(binaryTree, subMatrices, ancestorProbs, leaves, alphabetSize): - """ - calculates the un-normalised probabilties of each non-gap residue position - """ - l = {} - def upPass(binaryTree): - if binaryTree.internal: #is internal binaryTree - i = branchUp(binaryTree.left) - j = branchUp(binaryTree.right) - k = multiplyWV(i, j, alphabetSize) - l[binaryTree.traversalID.mid] = (k, i, j) - return k - l[binaryTree.traversalID.mid] = leaves[binaryTree.traversalID.leafNo] - return leaves[binaryTree.traversalID.leafNo] - def downPass(binaryTree, ancestorProbs): - if binaryTree.internal: #is internal binaryTree - i = l[binaryTree.traversalID.mid] - l[binaryTree.traversalID.mid] = multiplyWV(ancestorProbs, i[0], alphabetSize) - branchDown(binaryTree.left, multiplyWV(ancestorProbs, i[2], alphabetSize)) - branchDown(binaryTree.right, multiplyWV(ancestorProbs, i[1], alphabetSize)) - def branchUp(binaryTree): - return transformByDistance(upPass(binaryTree), subMatrices[binaryTree.traversalID.mid], alphabetSize) - def branchDown(binaryTree, ancestorProbs): - downPass(binaryTree, transformByDistance(ancestorProbs, subMatrices[binaryTree.traversalID.mid], alphabetSize)) - upPass(binaryTree) - downPass(binaryTree, ancestorProbs) - return l - -def calculateCharacterFrequencies(seq, map, alphabetSize): - counts = [0.0]*alphabetSize - for i in seq: - counts[map(i)] += 1 - return counts - -######################################################### -######################################################### -######################################################### -#distance matrix to tree building functions -######################################################### -######################################################### -######################################################### - -class DistancePair: - def __init__(self, distance, leaf1, leafNo1, leaf2, leafNo2): - self.distance = distance - self.leaf1 = leaf1 - self.leaf2 = leaf2 - self.leafNo1 = leafNo1 - self.leafNo2 = leafNo2 - - def __cmp__(self, distancePair): - if self.distance < distancePair.distance: - return -1 - if self.distance > distancePair.distance: - return 1 - return 0 #don't care - #doesn't wort for floats return self.distance.__cmp__(distancePair.distance) - -def correctTreeDistances(tree): - if tree is not None: - if tree.distance < MIN_TREE_DISTANCE: - tree.distance = MIN_TREE_DISTANCE - correctTreeDistances(tree.left) - correctTreeDistances(tree.right) - -def calculateDNADistanceMatrix(seqNo, fastaIter, transitionTransversionRatio=2.0): - transitions = [0.1]*seqNo*seqNo - transversions = [0.1]*seqNo*seqNo - counts = [1.0]*seqNo*seqNo - for column in fastaIter: - for i in xrange(0, seqNo): - if column[i] in [ 'A', 'C', 'T', 'G' ]: - for j in xrange(i+1, seqNo): - if column[j] in [ 'A', 'C', 'T', 'G' ]: - counts[i*seqNo + j] += 1 - if column[i] != column[j]: - if column[i] in [ 'A', 'G' ]: - if column[j] in [ 'C', 'T' ]: - transversions[i*seqNo + j] += 1 - else: - transitions[i*seqNo + j] += 1 - else: - if column[j] in [ 'A', 'G' ]: - transversions[i*seqNo + j] += 1 - else: - transitions[i*seqNo + j] += 1 - distanceMatrix = [ [None]*seqNo for i in xrange(0, seqNo) ] - for i in xrange(0, seqNo*seqNo): - for j in xrange(i+1, seqNo): - k = i * seqNo + j - distanceMatrix[i][j] = -0.75*math.log(1 - (4/3)*((transitions[k]+transversions[k])/counts[k])) #jukes cantor correction - distanceMatrix[j][i] = distanceMatrix[i][j] - #print "boo", i, j, distanceMatrix[i][j], (transitions[k]+transversions[k])/counts[k] - #distanceMatrix[i] = -0.5*math.log(1 - 2*P - Q)-0.25*math.log(1 - 2*Q) - return distanceMatrix - -def makeDistancePairs(distanceMatrix, iDs, seqNo): - binaryTrees = [ BinaryTree(0.0, False, None, None, iDs[i]) for i in xrange(0, seqNo) ] - distancePairs = [] - for i in xrange(0, seqNo): - for j in xrange(i+1, seqNo): - distancePairs.append(DistancePair(distanceMatrix[i][j], binaryTrees[i], 1, binaryTrees[j], 1)) - distancePairs.append(DistancePair(distanceMatrix[i][j], binaryTrees[j], 1, binaryTrees[i], 1)) - return distancePairs - -def upgma(distanceMatrix, iDs, leafNo): - binaryTree = upgmaI(makeDistancePairs(distanceMatrix, iDs, leafNo), leafNo) - def fn(tree): - if tree.internal: - tree.distance -= tree.left.distance - fn(tree.left) - fn(tree.right) - fn(binaryTree) - binaryTree.distance = MIN_TREE_DISTANCE - correctTreeDistances(binaryTree) - return binaryTree - -def upgmaI(distancePairs, leafNo): - #get min pair - distancePairs.sort() - distancePair = distancePairs[0] - #calculate shared distance - distancePair.leaf1.distance = distancePair.distance/2 - distancePair.leaf2.distance = distancePair.distance/2 - newLeaf = BinaryTree(0.0, True, distancePair.leaf1, distancePair.leaf2, None) - if leafNo-1 == 1: - return newLeaf - #replace references - holder1 = {} - holder2 = {} - newDistances = [] - for i in distancePairs: - if i.leaf1 == distancePair.leaf1 and i.leaf2 != distancePair.leaf2: - holder1[i.leaf2] = i - if i.leaf1 == distancePair.leaf2 and i.leaf2 != distancePair.leaf1: - holder2[i.leaf2] = i - assert len(holder1.keys()) == leafNo-2 - assert len(holder2.keys()) == leafNo-2 - assert set(holder1.keys()) == set(holder2.keys()) - for i in holder1.keys(): - j = holder1[i] - k = holder2[i] - newDistance = (j.distance*j.leafNo1 + k.distance*k.leafNo1)/(j.leafNo1 + k.leafNo1) - newDistances.append(DistancePair(newDistance, j.leaf2, j.leafNo2, newLeaf, j.leafNo1 + k.leafNo1)) - newDistances.append(DistancePair(newDistance, newLeaf, j.leafNo1 + k.leafNo1, j.leaf2, j.leafNo2)) - distancePairs = [ i for i in distancePairs if (i.leaf1 != distancePair.leaf1 and i.leaf1 != distancePair.leaf2 and i.leaf2 != distancePair.leaf1 and i.leaf2 != distancePair.leaf2) ] + newDistances - return upgmaI(distancePairs, leafNo-1) - -def nj(distanceMatrix, iDs, leafNo): - binaryTree = njI(makeDistancePairs(distanceMatrix, iDs, leafNo), leafNo) - correctTreeDistances(binaryTree) - return binaryTree - -def getMinPair(distancePairs, rValues, leafNo): - j = None - k = sys.maxint - for i in distancePairs: - adjustD = i.distance - (rValues[i.leaf1] + rValues[i.leaf2])/(leafNo-2) - #print "the adjusted value ", adjustD, i.distance, rValues[i.leaf1]/(leafNo-2), rValues[i.leaf2]/(leafNo-2) - if adjustD < k: - k = adjustD - j = i - #print "value is ", k, j.distance - return j - -def calculateRValues(distancePairs, leafNo): - j = {} - for i in distancePairs: - if j.has_key(i.leaf1): - j[i.leaf1] += i.distance - else: - j[i.leaf1] = i.distance - assert len(j.keys()) == leafNo - return j - -def njI(distancePairs, leafNo): - assert leafNo >= 2 - if leafNo == 2: - assert len(distancePairs) == 2 - distancePair = distancePairs[0] - distancePair.leaf1.distance = distancePair.distance*0.5 - distancePair.leaf2.distance = distancePair.distance*0.5 - return BinaryTree(MIN_TREE_DISTANCE, True, distancePair.leaf1, distancePair.leaf2, None) - #calculate r values - rValues = calculateRValues(distancePairs, leafNo) - #get min pair - distancePair = getMinPair(distancePairs, rValues, leafNo) - #distance, internal, left, right - distancePair.leaf1.distance = 0.5*(distancePair.distance + (rValues[distancePair.leaf1] - rValues[distancePair.leaf2])/(leafNo-2)) - distancePair.leaf2.distance = distancePair.distance - distancePair.leaf1.distance - newLeaf = BinaryTree(0.0, True, distancePair.leaf1, distancePair.leaf2, None) - #replace references - holder1 = {} - holder2 = {} - newDistances = [] - for i in distancePairs: - if i.leaf1 == distancePair.leaf1 and i.leaf2 != distancePair.leaf2: - holder1[i.leaf2] = i - if i.leaf1 == distancePair.leaf2 and i.leaf2 != distancePair.leaf1: - holder2[i.leaf2] = i - assert len(holder1.keys()) == leafNo-2 - assert len(holder2.keys()) == leafNo-2 - assert set(holder1.keys()) == set(holder2.keys()) - for i in holder1.keys(): - j = holder1[i] - k = holder2[i] - assert j.leaf2 == k.leaf2 - #print "the leaf is ", j.leaf2 - newDistance = 0.5*(j.distance + k.distance - distancePair.distance) - #print "now a new distance", newDistance - newDistances.append(DistancePair(newDistance, j.leaf2, 0, newLeaf, 0)) #leaf numbers are un important, and hence omitted - newDistances.append(DistancePair(newDistance, newLeaf, 0, j.leaf2, 0)) - distancePairs = [ i for i in distancePairs if (i.leaf1 != distancePair.leaf1 and i.leaf1 != distancePair.leaf2 and i.leaf2 != distancePair.leaf1 and i.leaf2 != distancePair.leaf2) ] + newDistances - return njI(distancePairs, leafNo-1) - -######################################################### -######################################################### -######################################################### -#substitution matrix functions -######################################################### -######################################################### -######################################################### - -def checkMatrix(m, fV, AS=4, reversible=True): - #print m - for i in xrange(0, AS): - j = sum(m[i]) - #print "AAAAA", j - assert j <= 1.0001 - assert j >= 0.9999 - if reversible: - for k in xrange(0, AS): - #print "comp2", (fV[i] * m[i][k]), (fV[k] * m[k][i] ) - assert close(fV[i] * m[i][k], fV[k] * m[k][i], 0.00001) - - wV = fV - wV2 = fV - wV3 = transformByDistance(wV, m, AS) - wV4 = transformByDistance(wV2, m, AS) - i = sum(multiplyWV(wV2, wV3, AS)) - j = sum(multiplyWV(wV, wV4, AS)) - #print i, j - assert close(i, j, 0.00001) - -def reverseSubMatrix(m, AS=4): - k = [ [None]*AS for i in xrange(0, AS) ] - for i in xrange(0, AS): - for j in xrange(0, AS): - k[j][i] = m[i][j] - return k - -def subMatrix_jukesCantor(d): - i = 0.25 + 0.75*math.exp(-(4.0/3.0)*d) - j = 0.25 - 0.25*math.exp(-(4.0/3.0)*d) - return [ [i, j, j, j], [j, i, j, j], [j, j, i, j], [j, j, j, i] ] - -""" -def distanceTamureiNei(aF, cF, gF, tF, a2G, t2C, tV): - rF = aF + gF - yF = cF + tF - - xx = 1.0 - a2G * rF/(2.0 * aF * gF) - tV/(2.0 * rF) - yy = 1.0 - t2C * yF/(2.0 * tF * cF) - tV/(2.0 * yF) - i = -(2.0 * aF * gF / rF) * math.log(1.0 - a2G * rF/(2.0 * aF * gF) - tV/(2.0 * rF)) - j = -(2.0 * tF * cF / yF) * math.log(1.0 - t2C * yF/(2.0 * tF * cF) - tV/(2.0 * yF)) - k = -2.0 * (rF * yF - (aF * gF * yF / rF) - (tF * cF * rF / yF)) * math.log(1.0 - tV/(2.0 * rF * yF)) - print i, j, k, xx, yy - d = -(2.0 * aF * gF / rF) * math.log(1.0 - a2G * rF/(2.0 * aF * gF) - tV/(2.0 * rF)) \ - -(2.0 * tF * cF / yF) * math.log(1.0 - t2C * yF/(2.0 * tF * cF) - tV/(2.0 * yF)) \ - -2.0 * (rF * yF - (aF * gF * yF / rF) - (tF * cF * rF / yF)) * math.log(1.0 - tV/(2.0 * rF * yF)) - return d -""" - -def subMatrix_TamuraNei(d, fA, fC, fG, fT, alphaPur, alphaPyr, beta): - i = fA + fC + fG + fT - assert i < 1.00001 - assert i > 0.99999 - assert d >= 0.0 - #assert alphaPur >= 0.0 - #assert alphaPyr >= 0.0 - #assert beta >= 0 - - AS = 4 - freq = ( fA, fC, fG, fT ) - alpha = ( alphaPur, alphaPyr, alphaPur, alphaPyr ) - matrix = [ [ 0.0 ]*AS for i in xrange(0, AS) ] - #see page 203 of Felsenstein's Inferring Phylogenies for explanation of calculations - def watKro(j, k): - if (j % 2) == (k % 2): - return 1.0 - return 0.0 - def kroenickerDelta(i, j): - if i == j: - return 1.0 - return 0.0 - for i in xrange(0, AS): #long winded, totally unoptimised method for calculating matrix - for j in xrange(0, AS): - l = 0.0 - for k in xrange(0, AS): - l += watKro(j, k) * freq[k] - matrix[i][j] =\ - math.exp(-(alpha[i] + beta) * d) * kroenickerDelta(i, j) + \ - math.exp(-beta*d) * (1.0 - math.exp(-alpha[i]*d)) * (freq[j] * watKro(i, j) / l) + \ - (1.0 - math.exp(-beta * d)) * freq[j] - checkMatrix(matrix, (fA, fC, fG, fT)) - return matrix - -def subMatrix_HKY(d, fA, fC, fG, fT, transitionTransversionR): - i = fA + fC + fG + fT - assert i < 1.00001 - assert i > 0.99999 - - fPur = fA + fG - fPyr = fC + fT - p = fPur/fPyr #makes like HKY - - beta = 1.0 / (2.0 * fPur * fPyr * (1.0 + transitionTransversionR)) - alphaPyr = ((fPur * fPyr * transitionTransversionR) - (fA * fG) - (fC * fT)) \ - / (2.0 * (1.0 + transitionTransversionR) * (fPyr * fA * fG * p + fPur * fC * fT)) - alphaPur = p * alphaPyr - return subMatrix_TamuraNei(d, fA, fC, fG, fT, alphaPur, alphaPyr, beta) - -def subMatrix_HalpernBruno(d, freqColumn, subMatrix, AS=4): - #return subMatrix_HKY(d, freqColumn[0], freqColumn[1], freqColumn[2], freqColumn[3], 2.0) - #return subMatrix - matrix = [ [ 0.0 ]*AS for i in xrange(0, AS) ] - for i in xrange(0, AS): - for j in xrange(0, AS): - a = freqColumn[i] * subMatrix[i][j] - b = freqColumn[j] * subMatrix[j][i] - if not close(a, b, 0.0001): - matrix[i][j] = subMatrix[i][j] * (math.log(b/a) / (1 - (a/b))) - else: - matrix[i][j] = subMatrix[i][j] - #for i in xrange(0, AS): - # #print matrix[i][i], sum(matrix[i]) - # matrix[i][i] -= sum(matrix[i]) - 1.0 - # assert matrix[i][i] >= 0 - #checkMatrix(matrix, freqColumn) - return matrix - -######################################################### -######################################################### -######################################################### -#misc tree functions -######################################################### -######################################################### -######################################################### - -def annotateTree(bT, fn): - """ - annotate a tree in an external array using the given function - """ - l = [None]*bT.traversalID.midEnd - def fn2(bT): - l[bT.traversalID.mid] = fn(bT) - if bT.internal: - fn2(bT.left) - fn2(bT.right) - fn2(bT) - return l - -def mapTraversalIDsBetweenTrees(oldTree, newTree): - map = {} - leafMap = {} - internalMap = {} - def fn(i): - j = i.traversalID.mid - if j == oldTree.traversalID.mid or (oldTree.internal and j == oldTree.left.traversalID.mid or j == oldTree.right.traversalID.mid): - return oldTree.traversalID.mid - return j - def fn2(oldTree): - if oldTree.internal: - fn2(oldTree.left) - fn2(oldTree.right) - else: - leafMap[oldTree.iD] = fn(oldTree) - fn2(oldTree) - def fn3(oldTree): - if oldTree.internal: - fn3(oldTree.left) - fn3(oldTree.right) - internalMap[(fn(oldTree.left), fn(oldTree.right))] = fn(oldTree) - internalMap[(fn(oldTree.right), fn(oldTree.left))] = fn(oldTree) - internalMap[(fn(oldTree), fn(oldTree.right))] = fn(oldTree.left) - internalMap[(fn(oldTree.right), fn(oldTree))] = fn(oldTree.left) - internalMap[(fn(oldTree), fn(oldTree.left))] = fn(oldTree.right) - internalMap[(fn(oldTree.left), fn(oldTree))] = fn(oldTree.right) - fn3(oldTree) - print leafMap - print internalMap - def fn4(newTree): - if newTree.internal: - fn4(newTree.left) - fn4(newTree.right) - map[newTree.traversalID.mid] = internalMap[(map[newTree.left.traversalID.mid], map[newTree.right.traversalID.mid])] - else: - map[newTree.traversalID.mid] = leafMap[newTree.iD] - fn4(newTree) - return map - -def remodelTreeRemovingRoot(root, node): - """ - Node is mid order number - """ - import bioio - assert root.traversalID.mid != node - hash = {} - def fn(bT): - if bT.traversalID.mid == node: - assert bT.internal == False - return [ bT ] - elif bT.internal: - i = fn(bT.left) - if i is None: - i = fn(bT.right) - if i is not None: - hash[i[-1]]= bT - i.append(bT) - return i - return None - l = fn(root) - def fn2(i, j): - if i.left == j: - return i.right - assert i.right == j - return i.left - def fn3(bT): - if hash[bT] == root: - s = '(' + bioio.printBinaryTree(fn2(hash[bT], bT), bT, True)[:-1] + ')' - else: - s = '(' + bioio.printBinaryTree(fn2(hash[bT], bT), bT, True)[:-1] + ',' + fn3(hash[bT]) + ')' - return s + ":" + str(bT.distance) - s = fn3(l[0]) + ';' - t = bioio.newickTreeParser(s) - return t - -def moveRoot(root, branch): - """ - Removes the old root and places the new root at the mid point along the given branch - """ - import bioio - if root.traversalID.mid == branch: - return bioio.newickTreeParser(bioio.printBinaryTree(root, True)) - def fn2(tree, seq): - if seq is not None: - return '(' + bioio.printBinaryTree(tree, True)[:-1] + ',' + seq + ')' - return bioio.printBinaryTree(tree, True)[:-1] - def fn(tree, seq): - if tree.traversalID.mid == branch: - i = tree.distance - tree.distance /= 2 - seq = '(' + bioio.printBinaryTree(tree, True)[:-1] + ',(' + seq + ('):%s' % tree.distance) + ');' - tree.distance = i - return seq - if tree.internal: - if branch < tree.traversalID.mid: - seq = fn2(tree.right, seq) - return fn(tree.left, seq) - else: - assert branch > tree.traversalID.mid - seq = fn2(tree.left, seq) - return fn(tree.right, seq) - else: - return bioio.printBinaryTree(tree, True)[:-1] - s = fn(root, None) - return bioio.newickTreeParser(s) - -def checkGeneTreeMatchesSpeciesTree(speciesTree, geneTree, processID): - """ - Function to check ids in gene tree all match nodes in species tree - """ - def fn(tree, l): - if tree.internal: - fn(tree.left, l) - fn(tree.right, l) - else: - l.append(processID(tree.iD)) - l = [] - fn(speciesTree, l) - l2 = [] - fn(geneTree, l2) - for i in l2: - #print "node", i, l - assert i in l - -def calculateDupsAndLossesByReconcilingTrees(speciesTree, geneTree, processID): - """ - Reconciles the given gene tree with the species tree and - report the number of needed duplications and losses - """ - checkGeneTreeMatchesSpeciesTree(speciesTree, geneTree, processID) - def fn(tree, m): - if tree.internal: - nodes = fn(tree.left, m) - nodes = nodes.union(fn(tree.right, m)) - m[tree.traversalID.mid] = nodes - else: - m[tree.traversalID.mid] = set((processID(tree.iD),)) - return m[tree.traversalID.mid] - a = {} - fn(speciesTree, a) - b = {} - fn(geneTree, b) - def fn2(nodes, speciesTree): - assert nodes.issubset(a[speciesTree.traversalID.mid]) - if speciesTree.internal: - if nodes.issubset(a[speciesTree.left.traversalID.mid]): - return fn2(nodes, speciesTree.left) - if nodes.issubset(a[speciesTree.right.traversalID.mid]): - return fn2(nodes, speciesTree.right) - return speciesTree.traversalID.mid - for iD in b.keys(): - nodes = b[iD] - b[iD] = fn2(nodes, speciesTree) - dups = [] - def fn3(geneTree): - if geneTree.internal: - i = b[geneTree.traversalID.mid] - if b[geneTree.left.traversalID.mid] == i or b[geneTree.right.traversalID.mid] == i: - dups.append(geneTree.traversalID.mid) - fn3(geneTree.left) - fn3(geneTree.right) - fn3(geneTree) - lossMap = {} - def fn4(speciesTree): - nodes = [(speciesTree.traversalID.mid, -1)] - lossMap[(speciesTree.traversalID.mid, speciesTree.traversalID.mid)] = 0 - if speciesTree.internal: - for node, losses in fn4(speciesTree.left) + fn4(speciesTree.right): - lossMap[(speciesTree.traversalID.mid, node)] = losses+1 - nodes.append((node, losses+1)) - return nodes - for node, losses in fn4(speciesTree): - lossMap[(sys.maxint, node)] = losses+1 - losses = [0] - def fn5(geneTree, ancestor): - if geneTree.internal: - i = b[geneTree.traversalID.mid] - if geneTree.traversalID.mid in dups: - losses[0] += lossMap[(ancestor, b[geneTree.left.traversalID.mid])] - losses[0] += lossMap[(ancestor, b[geneTree.right.traversalID.mid])] - else: - losses[0] += lossMap[(i, b[geneTree.left.traversalID.mid])] - losses[0] += lossMap[(i, b[geneTree.right.traversalID.mid])] - fn5(geneTree.left, i) - fn5(geneTree.right, i) - ancestorHolder = [None] - def fn6(speciesTree, ancestor, node): - if speciesTree.traversalID.mid == node: - ancestorHolder[0] = ancestor - if speciesTree.internal: - fn6(speciesTree.left, speciesTree.traversalID.mid, node) - fn6(speciesTree.right, speciesTree.traversalID.mid, node) - ancestor = fn6(speciesTree, sys.maxint, b[geneTree.traversalID.mid]) - assert ancestorHolder[0] is not None - fn5(geneTree, ancestorHolder[0]) - return len(dups), losses[0] - -def calculateProbableRootOfGeneTree(speciesTree, geneTree, processID=lambda x : x): - """ - Goes through each root possible branch making it the root. - Returns tree that requires the minimum number of duplications. - """ - #get all rooted trees - #run dup calc on each tree - #return tree with fewest number of dups - if geneTree.traversalID.midEnd <= 3: - return (0, 0, geneTree) - checkGeneTreeMatchesSpeciesTree(speciesTree, geneTree, processID) - l = [] - def fn(tree): - if tree.traversalID.mid != geneTree.left.traversalID.mid and tree.traversalID.mid != geneTree.right.traversalID.mid: - newGeneTree = moveRoot(geneTree, tree.traversalID.mid) - binaryTree_depthFirstNumbers(newGeneTree) - dupCount, lossCount = calculateDupsAndLossesByReconcilingTrees(speciesTree, newGeneTree, processID) - l.append((dupCount, lossCount, newGeneTree)) - if tree.internal: - fn(tree.left) - fn(tree.right) - fn(geneTree) - l.sort() - return l[0][2], l[0][0], l[0][1] - -#add traversalID.mid to each node name -#print tree -#parse tree -#remove names, and add them to traversalID - -def main(): - pass - -def _test(): - import doctest - return doctest.testmod() - -if __name__ == '__main__': - _test() - main() diff --git a/treeTest.py b/treeTest.py deleted file mode 100644 index e7c6c9a..0000000 --- a/treeTest.py +++ /dev/null @@ -1,219 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt - -import unittest -import random - -from tree import remodelTreeRemovingRoot -from tree import binaryTree_depthFirstNumbers -from tree import mapTraversalIDsBetweenTrees -from tree import BinaryTree -from bioio import printBinaryTree -from bioio import newickTreeParser -from misc import close -from tree import moveRoot -from tree import calculateDupsAndLossesByReconcilingTrees -from tree import calculateProbableRootOfGeneTree -from sonLib.bioio import TestStatus - -class TestCase(unittest.TestCase): - - def setUp(self): - self.testNo = TestStatus.getTestSetup() - unittest.TestCase.setUp(self) - - def tearDown(self): - unittest.TestCase.tearDown(self) - - def testRemodelTreeRemovingRoot(self): - for test in xrange(0, self.testNo): - binaryTree = getRandomTree() - binaryTree_depthFirstNumbers(binaryTree) - node = getRandomLeafNode(binaryTree) - remodTree = remodelTreeRemovingRoot(binaryTree, node.traversalID.mid) - print "test", test, printBinaryTree(binaryTree, True), printBinaryTree(node, True), printBinaryTree(remodTree, True) - binaryTree_depthFirstNumbers(remodTree) - distances = mapTraversalIDsBetweenTrees(binaryTree, remodTree) - d = getDistancesBetweenLeaves(binaryTree) - d2 = getDistancesBetweenLeaves(remodTree) - print d - print d2 - for key in d2: - assert close(d2[key], d[key], 0.0001) - - def testMoveRoot(self): - for test in xrange(0, self.testNo): - binaryTree = getRandomTree() - binaryTree_depthFirstNumbers(binaryTree) - node = getRandomNode(binaryTree) - print "before", printBinaryTree(binaryTree, True), printBinaryTree(node, True) - remodTree = moveRoot(binaryTree, node.traversalID.mid) - print "test", test, printBinaryTree(binaryTree, True), printBinaryTree(node, True), printBinaryTree(remodTree, True) - binaryTree_depthFirstNumbers(remodTree) - #distances = mapTraversalIDsBetweenTrees(binaryTree, remodTree) - #d = getDistancesBetweenLeaves(binaryTree) - #d2 = getDistancesBetweenLeaves(remodTree) - #print d - #print d2 - #for key in d2: - # assert close(d2[key], d[key], 0.0001) - - def testCalculateDupsAndLossesByReconcilingTrees(self): - for test in xrange(0, self.testNo): - speciesTree = getRandomTree() - binaryTree_depthFirstNumbers(speciesTree) - geneTree = getRandomTree() - binaryTree_depthFirstNumbers(geneTree) - l = [-1] - def fn(): - l[0] += 1 - return str(l[0]) - labelTree(speciesTree, fn) - def fn2(): - return str(int(l[0]*random.random())) - labelTree(geneTree, fn2) - calculateDupsAndLossesByReconcilingTrees(speciesTree, geneTree, processID=lambda x : x) - - def testCalculateDupsAndLossesByReconcilingTrees_Examples(self): - treeString = '(((((((((((((human:0.006969,chimp:0.009727):0.025291,((baboon:0.008968):0.011019):0.024581):0.023649):0.066673):0.018405,((rat:0.081244,mouse:0.072818):0.238435):0.021892):0.02326,(((cow:0.164728,(cat:0.109852,dog:0.107805):0.049576):0.004663):0.010883):0.033242):0.028346):0.016015):0.226853):0.063898):0.126639):0.119814):0.16696);' - speciesTree = newickTreeParser(treeString) - binaryTree_depthFirstNumbers(speciesTree) - #s = printBinaryTree(speciesTree, True) - #speciesTree = newickTreeParser(s) - #binaryTree_depthFirstNumbers(speciesTree) - - geneString1 = ('((human,baboon),chimp);', 1, 3) - geneString2 = ('((human,chimp),baboon);', 0, 0) - geneString3 = ('((human,(human, chimp)),baboon);', 1, 1) - geneString4 = ('((human,(human, chimp)),(chimp, baboon));', 2, 3) - - geneString5 = ('(dog,cat);', 0, 0) - geneString6 = ('((dog,cat), cow);', 0, 0) - geneString7 = ('(cow,(dog,cat));', 0, 0) - geneString8 = ('(cow,(cat,dog));', 0, 0) - - geneString9 = ('((cow,dog),(dog,cow));', 1, 2) - geneString10 = ('((cow,(cow,cow)),(dog,cat));', 2, 0) - geneString11 = ('((cow,(cow,cow)),(dog,((cat,cat),cat)));', 4, 0) - - geneStrings = [ geneString1, geneString2, geneString3, geneString4, \ - geneString5, geneString6, geneString7, geneString8, - geneString9, geneString10, geneString11 ] - print "" - for geneString, dupCount, lossCount in geneStrings: - geneTree = newickTreeParser(geneString) - binaryTree_depthFirstNumbers(geneTree) - print printBinaryTree(geneTree, True), printBinaryTree(speciesTree, True) - dupCount2, lossCount2 = calculateDupsAndLossesByReconcilingTrees(speciesTree, geneTree, processID=lambda x : x) - print geneString, "dups", dupCount, dupCount2, "losses", lossCount, lossCount2 - assert dupCount == dupCount2 - assert lossCount == lossCount2 - - def testCalculateProbableRootOfGeneTree_Examples(self): - #return - treeString = '(((((((((((((human:0.006969,chimp:0.009727):0.025291,((baboon:0.008968):0.011019):0.024581):0.023649):0.066673):0.018405,((rat:0.081244,mouse:0.072818):0.238435):0.021892):0.02326,(((cow:0.164728,(cat:0.109852,dog:0.107805):0.049576):0.004663):0.010883):0.033242):0.028346):0.016015):0.226853):0.063898):0.126639):0.119814):0.16696);' - speciesTree = newickTreeParser(treeString) - binaryTree_depthFirstNumbers(speciesTree) - - geneString1 = ('((human,baboon),chimp);', '((human,chimp),baboon);') - geneString2 = ('((human,chimp),baboon);', '((human,chimp),baboon);') - geneString3 = ('((((human,chimp),baboon),((dog,cat),cow)),(mouse,rat));', '((((human,chimp),baboon),(mouse,rat)),((dog,cat),cow));') - geneString4 = ('((((human,chimp),baboon),(mouse,rat)),((dog,cat),cow));', '((((human,chimp),baboon),(mouse,rat)),((dog,cat),cow));') - geneString5 = ('((((human,(chimp, chimp)),baboon),((dog,cat),cow)),(mouse,rat));', '((((human,(chimp,chimp)),baboon),(mouse,rat)),((dog,cat),cow));') - #geneString3 = ('((human,(human, chimp)),baboon);', 1) - #geneString4 = ('((human,(human, chimp)),(chimp, baboon));', 2) - - #geneString5 = ('(dog,cat);', 0) - #geneString6 = ('((dog,cat), cow);', 0) - #geneString7 = ('(cow,(dog,cat));', 0) - #geneString8 = ('(cow,(cat,dog));', 0) - - #geneString9 = ('((cow,dog),(dog,cow));', 1) - #geneString10 = ('((cow,(cow,cow)),(dog,cat));', 2) - #geneString11 = ('((cow,(cow,cow)),(dog,((cat,cat),cat)));', 4) - - geneStrings = [ geneString1, geneString2, geneString3, geneString4, geneString5 ] - #[ geneString3, geneString4, \ - #geneString5, geneString6, geneString7, geneString8, - #geneString9, geneString10, geneString11 ] - for geneString, rootedGeneString in geneStrings: - geneTree = newickTreeParser(geneString) - rootedGeneTree = newickTreeParser(geneString) - binaryTree_depthFirstNumbers(geneTree) - rootedGeneTree2, dupCount, lossCount = calculateProbableRootOfGeneTree(speciesTree, geneTree) - print "rootedGeneTree", rootedGeneString, dupCount, lossCount, printBinaryTree(rootedGeneTree2, False) - #assert printBinaryTree(rootedGeneTree, False) == printBinaryTree(rootedGeneTree2, False) - - def testCalculateProbableRootOfGeneTree(self): - for test in xrange(0, self.testNo): - speciesTree = getRandomTree() - binaryTree_depthFirstNumbers(speciesTree) - geneTree = getRandomTree() - binaryTree_depthFirstNumbers(geneTree) - l = [-1] - def fn(): - l[0] += 1 - return str(l[0]) - labelTree(speciesTree, fn) - def fn2(): - return str(int(l[0]*random.random())) - labelTree(geneTree, fn2) - calculateProbableRootOfGeneTree(speciesTree, geneTree) - -def getDistancesBetweenLeaves(tree): - distances = {} - def fn(tree): - if tree.internal: - i = fn(tree.left) - j = fn(tree.right) - for k, l in i: - for m, n in j: - distances[(k, m)] = l + n - distances[(m, k)] = l + n - return [ (k, l + tree.distance) for k, l in (i + j) ] - return [ (tree.iD, tree.distance) ] - fn(tree) - return distances - -def getRandomTree(distance=lambda : random.random()*0.8): - leafNo = [-1] - counter = [0] - def fn(): - if random.random() > 0.6: - return BinaryTree(distance(), True, fn(), fn(), None) - else: - leafNo[0] += 1 - return BinaryTree(distance(), False, None, None, str(leafNo[0])) - return BinaryTree(random.random(), True, fn(), fn(), None) - -def getRandomLeafNode(tree): - if tree.internal: - #return randomBranch(tree.left) - if random.random() > 0.5: - return getRandomLeafNode(tree.left) - else: - return getRandomLeafNode(tree.right) - return tree - -def getRandomNode(tree): - if tree.internal: - if random.random() > 0.5: - return tree - if random.random() > 0.5: - return getRandomLeafNode(tree.left) - else: - return getRandomLeafNode(tree.right) - return tree - -def labelTree(tree, fn): - if tree.internal: - labelTree(tree.left, fn) - labelTree(tree.right, fn) - else: - tree.iD = fn() - -if __name__ == '__main__': - unittest.main() diff --git a/unitTest.py b/unitTest.py deleted file mode 100644 index b561105..0000000 --- a/unitTest.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python - -#Copyright (C) 2006-2012 by Benedict Paten (benedictpaten@gmail.com) -# -#Released under the MIT license, see LICENSE.txt - -""" -Support for unit testing. -""" -import os, unittest - -class TestCase(unittest.TestCase): - """A class that add specialized support methods for test cases""" - - def getTestTempFile(self, suffix): - "create a temporary file based on test case name" - tempDir = "tmp" - if not os.path.exists(tempDir): - os.makedirs(tempDir) - tempFile = tempDir + "/" + self.id() + "." + suffix - if os.path.exists(tempFile): - os.unlink(tempFile) - return tempFile -