diff --git a/extras/tests/scripts/testSuffixComparator.sh b/extras/tests/scripts/testSuffixComparator.sh new file mode 100755 index 00000000..3f5894b9 --- /dev/null +++ b/extras/tests/scripts/testSuffixComparator.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" +build_dir="$(mktemp -d)" +trap 'rm -rf "${build_dir}"' EXIT + +"${CXX:-g++}" \ + -std=c++11 -Wall -Wextra -fsanitize=address,undefined \ + -I"${repo_dir}/source" \ + "${repo_dir}/extras/tests/testSuffixComparator.cpp" \ + "${repo_dir}/source/funCompareUintAndSuffixesMemcmp.cpp" \ + -o "${build_dir}/testSuffixComparator" + +ASAN_OPTIONS=detect_leaks=0 "${build_dir}/testSuffixComparator" diff --git a/extras/tests/testSuffixComparator.cpp b/extras/tests/testSuffixComparator.cpp new file mode 100644 index 00000000..39b7e98a --- /dev/null +++ b/extras/tests/testSuffixComparator.cpp @@ -0,0 +1,52 @@ +#include "funCompareUintAndSuffixesMemcmp.h" + +#include +#include +#include +#include + +namespace { + +struct Entry { + uint64_t insertionPoint; + uint64_t suffix; +}; + +bool expectSign(const Entry &left, const Entry &right, int expectedSign, const char *label) +{ + int result=funCompareUintAndSuffixesMemcmp(&left, &right); + int resultSign=(result>0)-(result<0); + if (resultSign!=expectedSign) + { + std::cerr << label << ": expected sign " << expectedSign << ", observed " << resultSign << '\n'; + return false; + }; + return true; +} + +} + +int main() +{ + std::vector sequence={0,1,3,5, 0,1,2,5, 0,1,3,5, 2,2,2,5}; + g_funCompareUintAndSuffixesMemcmp_G=sequence.data(); + g_funCompareUintAndSuffixesMemcmp_N=sequence.size()-1; + g_funCompareUintAndSuffixesMemcmp_L=std::numeric_limits::max(); + + Entry a={7,0}; + Entry b={7,4}; + Entry sameSuffix={7,8}; + Entry earlierBucket={6,12}; + + bool ok=true; + ok &= expectSign(a, b, 1, "suffix order"); + ok &= expectSign(b, a, -1, "reverse suffix order"); + ok &= expectSign(a, sameSuffix, -1, "identical suffix tie break"); + ok &= expectSign(a, a, 0, "self comparison"); + ok &= expectSign(earlierBucket, a, -1, "insertion point order"); + + g_funCompareUintAndSuffixesMemcmp_L=2; + ok &= expectSign(a, b, -1, "finite prefix tie break"); + + return ok ? 0 : 1; +} diff --git a/source/funCompareUintAndSuffixesMemcmp.cpp b/source/funCompareUintAndSuffixesMemcmp.cpp index 46734178..e5cadfce 100644 --- a/source/funCompareUintAndSuffixesMemcmp.cpp +++ b/source/funCompareUintAndSuffixesMemcmp.cpp @@ -1,13 +1,14 @@ #include "funCompareUintAndSuffixesMemcmp.h" -#include //for memcmp +#include "IncludeDefine.h" char* g_funCompareUintAndSuffixesMemcmp_G; +uint64_t g_funCompareUintAndSuffixesMemcmp_N; uint64_t g_funCompareUintAndSuffixesMemcmp_L; int funCompareUintAndSuffixesMemcmp ( const void *a, const void *b) { - uint64_t* va= ((uint64_t*) a); - uint64_t* vb= ((uint64_t*) b); + const uint64_t* va=static_cast(a); + const uint64_t* vb=static_cast(b); if (va[0]>vb[0]) { @@ -17,17 +18,34 @@ int funCompareUintAndSuffixesMemcmp ( const void *a, const void *b) return -1; } else {//compare suffixes -// char *p5=(char*) memchr(g_funCompareUintAndSuffixesMemcmp_G+va[1],5,g_funCompareUintAndSuffixesMemcmp_L); //first encounter of char=5 -// char *p5=g_funCompareUintAndSuffixesMemcmp_G+va[1]+g_funCompareUintAndSuffixesMemcmp_L; - //compare suffixes but only until first char=5 -// int comp=memcmp(g_funCompareUintAndSuffixesMemcmp_G+va[1],g_funCompareUintAndSuffixesMemcmp_G+vb[1],p5+1-(g_funCompareUintAndSuffixesMemcmp_G+va[1])); - int comp=memcmp(g_funCompareUintAndSuffixesMemcmp_G+va[1],g_funCompareUintAndSuffixesMemcmp_G+vb[1],g_funCompareUintAndSuffixesMemcmp_L); + const char* ga=g_funCompareUintAndSuffixesMemcmp_G+va[1]; + const char* gb=g_funCompareUintAndSuffixesMemcmp_G+vb[1]; + uint64_t compareLength=0; + if (va[1](memchr(ga, GENOME_spacingChar, compareLength)); + if (sentinel!=NULL) + { + compareLength=sentinel-ga+1; + }; + }; + + int comp=memcmp(ga, gb, compareLength); + if (comp!=0) + { + return comp; + }; - if (comp==0) + if (va[1]>vb[1]) + { + return 1; + } else if (va[1]vb[1] ? 1 : -1; + return -1; }; -// int comp=va[1]>vb[1] ? 1 : -1; - return comp; + return 0; }; }; diff --git a/source/funCompareUintAndSuffixesMemcmp.h b/source/funCompareUintAndSuffixesMemcmp.h index 83c6f92f..f2584169 100644 --- a/source/funCompareUintAndSuffixesMemcmp.h +++ b/source/funCompareUintAndSuffixesMemcmp.h @@ -4,7 +4,9 @@ #include extern char* g_funCompareUintAndSuffixesMemcmp_G; +extern uint64_t g_funCompareUintAndSuffixesMemcmp_N; +// Maximum number of bases to compare; UINT64_MAX means compare to the sentinel. extern uint64_t g_funCompareUintAndSuffixesMemcmp_L; int funCompareUintAndSuffixesMemcmp ( const void *a, const void *b); -#endif \ No newline at end of file +#endif diff --git a/source/insertSeqSA.cpp b/source/insertSeqSA.cpp index e98ebcde..589dce31 100644 --- a/source/insertSeqSA.cpp +++ b/source/insertSeqSA.cpp @@ -109,7 +109,8 @@ uint insertSeqSA(PackedArray & SA, PackedArray & SA1, PackedArray & SAi, char * */ g_funCompareUintAndSuffixesMemcmp_G=seq1[0]; - g_funCompareUintAndSuffixesMemcmp_L=mapGen.pGe.gSuffixLengthMax/sizeof(uint64_t); + g_funCompareUintAndSuffixesMemcmp_N=2*nG1; + g_funCompareUintAndSuffixesMemcmp_L=mapGen.pGe.gSuffixLengthMax; qsort((void*) indArray, nInd, 2*sizeof(uint64_t), funCompareUintAndSuffixesMemcmp); // qsort((void*) indArray, nInd, 2*sizeof(uint64), funCompareUint2);