From dfcbc6d5b8c6636bbb3ca1b3437fbdf9a8d5aada Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 17 Mar 2017 18:22:16 -0400 Subject: [PATCH] Implemented logicalorCount + bug fixes in logicalxorCount --- include/concise.h | 53 +++++++++++++++++++++++++++++++++++++++++++---- tests/unit.cpp | 8 +++++++ 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/include/concise.h b/include/concise.h index b15c198..3049670 100644 --- a/include/concise.h +++ b/include/concise.h @@ -473,7 +473,49 @@ template class ConciseSet { return answer; } - + size_t logicalorCount(const ConciseSet &other) const { + if (this->isEmpty()) { + return other.size(); + } + if (other.isEmpty()) { + return this->size(); + } + size_t answer = 0; + // scan "this" and "other" + WordIterator thisItr(*this); + WordIterator otherItr(other); + while (true) { + if (!thisItr.IsLiteral) { + if (!otherItr.IsLiteral) { + int minCount = std::min(thisItr.count, otherItr.count); + if((thisItr.word | otherItr.word) & SEQUENCE_BIT) + answer += 31 * minCount; + if (!thisItr.prepareNext(minCount) | + !otherItr.prepareNext(minCount)) // NOT || + break; + } else { + answer += getLiteralBitCount(thisItr.toLiteral() | otherItr.word); + thisItr.word--; + if (!thisItr.prepareNext(1) | + !otherItr.prepareNext()) // do NOT use "||" + break; + } + } else if (!otherItr.IsLiteral) { + answer += getLiteralBitCount(thisItr.word | otherItr.toLiteral()); + otherItr.word--; + if (!thisItr.prepareNext() | + !otherItr.prepareNext(1)) // do NOT use "||" + break; + } else { + answer += getLiteralBitCount(thisItr.word | otherItr.word); + if (!thisItr.prepareNext() | !otherItr.prepareNext()) // do NOT use "||" + break; + } + } + answer += thisItr.flushCount(); + answer += otherItr.flushCount(); + return answer; + } void clear() { reset(); } @@ -1028,20 +1070,23 @@ template class WordIterator { uint32_t flushCount() { + if(exhausted()) return 0; uint32_t cardsize = 0; - while(!exhausted()) { + do { if (IsLiteral) { cardsize += getLiteralBitCount(word); } else { - if(word & SEQUENCE_BIT) + if(word & SEQUENCE_BIT) { cardsize += 31 * count; + } } } while (prepareNext()); return cardsize; } bool flushEmpty() { - while(!exhausted()) { + if(exhausted()) return true; + do { if (IsLiteral) { if(!isLiteralZero(word)) return false; } else { diff --git a/tests/unit.cpp b/tests/unit.cpp index 739fde5..a9e59e0 100644 --- a/tests/unit.cpp +++ b/tests/unit.cpp @@ -154,6 +154,7 @@ template void basictest() { assert(test2.contains(3000)); assert(test2.size() == 5); ConciseSet tmp; + assert(test1.logicalorCount(test2) == 7); tmp = test1.logicalor(test2); assert(tmp.size() == 7); assert(test1.logicalandCount(test2) == 3); @@ -205,6 +206,7 @@ template void longtest() { assert(test2.size() == 1000); ConciseSet tmp; + assert(test1.logicalorCount(test2) == 2000); tmp = test1.logicalor(test2); assert(tmp.size() == 2000); for (int k = 0; k < 1000; ++k) { @@ -321,7 +323,9 @@ template void toytest() { std::set truesymsubtract = symmetrically_subtract(set1, set2); ConciseSet union1; ConciseSet union2; + size_t expunion1 = test1.logicalorCount(test2); union1 = test1.logicalor(test2); + assert(union1.size() == expunion1); union2 = test1.logicalor(test2); assert(equals(trueunion, union1)); assert(equals(trueunion, union2)); @@ -417,7 +421,9 @@ template void variedtest() { ConciseSet union1; ConciseSet union2; + size_t expunion1 = test1.logicalorCount(test2); union1 = test1.logicalor(test2); + assert(union1.size() == expunion1); union2 = test1.logicalor(test2); assert(equals(trueunion, union1)); assert(equals(trueunion, union2)); @@ -575,7 +581,9 @@ template void realtest() { ConciseSet union1; ConciseSet union2; + size_t expunion1 = test1.logicalorCount(test2); union1 = test1.logicalor(test2); + assert(union1.size() == expunion1); union2 = test1.logicalor(test2); assert(equals(trueunion, union1)); assert(equals(trueunion, union2));