Skip to content

Commit

Permalink
Implemented equality.
Browse files Browse the repository at this point in the history
  • Loading branch information
lemire committed Mar 7, 2017
1 parent b04a575 commit 0f6f88b
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 6 deletions.
117 changes: 117 additions & 0 deletions include/concise.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,96 @@ template <bool wah_mode = false> class ConciseSet {
return;
}

bool equals(const ConciseSet<wah_mode> &other) const {
return logicalxorEmpty(other);
}

bool logicalxorEmpty(const ConciseSet<wah_mode> &other) const {
if (this->isEmpty()) {
return other.isEmpty();
}
if (other.isEmpty()) {
return this->isEmpty();
}
// scan "this" and "other"
WordIterator<wah_mode> thisItr(*this);
WordIterator<wah_mode> otherItr(other);
while (true) {
if (!thisItr.IsLiteral) {
if (!otherItr.IsLiteral) {
int minCount = std::min(thisItr.count, otherItr.count);
if(concise_xor(thisItr.word, otherItr.word) & SEQUENCE_BIT)
return false;
if (!thisItr.prepareNext(minCount) |
!otherItr.prepareNext(minCount)) // NOT ||
break;
} else {
if(!isLiteralZero(concise_xor(thisItr.toLiteral(), otherItr.word))) return false;
thisItr.word--;
if (!thisItr.prepareNext(1) |
!otherItr.prepareNext()) // do NOT use "||"
break;
}
} else if (!otherItr.IsLiteral) {
if(!isLiteralZero(concise_xor(thisItr.word, otherItr.toLiteral()))) return false;
otherItr.word--;
if (!thisItr.prepareNext() |
!otherItr.prepareNext(1)) // do NOT use "||"
break;
} else {
if(!isLiteralZero(concise_xor(thisItr.word, otherItr.word))) return false;
if (!thisItr.prepareNext() | !otherItr.prepareNext()) // do NOT use "||"
break;
}
}
if(thisItr.flushEmpty() && otherItr.flushEmpty()) return true;
return false;
}

size_t logicalxorCount(const ConciseSet<wah_mode> &other) const {
if (this->isEmpty()) {
return other.size();
}
if (other.isEmpty()) {
return this->size();
}
size_t answer = 0;
// scan "this" and "other"
WordIterator<wah_mode> thisItr(*this);
WordIterator<wah_mode> otherItr(other);
while (true) {
if (!thisItr.IsLiteral) {
if (!otherItr.IsLiteral) {
int minCount = std::min(thisItr.count, otherItr.count);
if(concise_xor(thisItr.word, otherItr.word) & SEQUENCE_BIT)
answer += 31 * minCount;
if (!thisItr.prepareNext(minCount) |
!otherItr.prepareNext(minCount)) // NOT ||
break;
} else {
answer += getLiteralBitCount(concise_xor(thisItr.toLiteral(), otherItr.word));
thisItr.word--;
if (!thisItr.prepareNext(1) |
!otherItr.prepareNext()) // do NOT use "||"
break;
}
} else if (!otherItr.IsLiteral) {
answer += getLiteralBitCount(concise_xor(thisItr.word, otherItr.toLiteral()));
otherItr.word--;
if (!thisItr.prepareNext() |
!otherItr.prepareNext(1)) // do NOT use "||"
break;
} else {
answer += getLiteralBitCount(concise_xor(thisItr.word, otherItr.word));
if (!thisItr.prepareNext() | !otherItr.prepareNext()) // do NOT use "||"
break;
}
}
answer += thisItr.flushCount();
answer += otherItr.flushCount();
return answer;
}

void clear() { reset(); }

void add(uint32_t e) {
Expand Down Expand Up @@ -854,6 +944,33 @@ template <bool wah_mode = false> class WordIterator {
*/
uint32_t count;



uint32_t flushCount() {
uint32_t cardsize = 0;
while(!exhausted()) {
if (IsLiteral) {
cardsize += getLiteralBitCount(word);
} else {
if(word & SEQUENCE_BIT)
cardsize += 31 * count;
}
} while (prepareNext());
return cardsize;
}

bool flushEmpty() {
while(!exhausted()) {
if (IsLiteral) {
if(!isLiteralZero(word)) return false;
} else {
if(word & SEQUENCE_BIT)
return false;
}
} while (prepareNext());
return true;
}

bool flush(ConciseSet<wah_mode> &s) {
// nothing to flush
if (exhausted())
Expand Down
14 changes: 8 additions & 6 deletions include/conciseutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,18 @@ static inline int getFlippedBit(uint32_t word) {
// set
return ((word >> 25) & UINT32_C(0x0000001F)) - 1;
}
static inline uint32_t concise_or(uint32_t literal1, uint32_t literal2) {
return ALL_ZEROS_LITERAL | (literal1 | literal2);
}

static inline uint32_t concise_and(uint32_t literal1, uint32_t literal2) {
return ALL_ZEROS_LITERAL | (literal1 & literal2);
}
static inline uint32_t concise_xor(uint32_t literal1, uint32_t literal2) {
return ALL_ZEROS_LITERAL | (literal1 ^ literal2);
}
static inline uint32_t concise_andnot(uint32_t literal1, uint32_t literal2) {
return ALL_ZEROS_LITERAL | (literal1 & (~literal2));
}

static inline uint32_t concise_and(uint32_t literal1, uint32_t literal2) {
return ALL_ZEROS_LITERAL | (literal1 & literal2);
}

/**
* Gets the bits contained within the literal word
*/
Expand All @@ -170,4 +168,8 @@ static inline int getLiteralBitCount(uint32_t word) {
return __builtin_popcount(getLiteralBits(word));
}

static inline bool isLiteralZero(uint32_t word) {
return getLiteralBits(word) == 0;
}

#endif
8 changes: 8 additions & 0 deletions tests/unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,13 +545,21 @@ template <bool wahmode> void realtest() {
test2.add(data2[k]);
set2.insert(data2[k]);
}


assert(test1.equals(test1));
assert(test2.equals(test2));
assert(!test2.equals(test1));
assert(!test1.equals(test2));

std::set<uint32_t> trueunion = unite(set1, set2);
std::set<uint32_t> trueinter = intersect(set1, set2);
std::set<uint32_t> truesubtract = subtract(set1, set2);
std::set<uint32_t> truesymsubtract = symmetrically_subtract(set1, set2);

ConciseSet<wahmode> union1;
ConciseSet<wahmode> union2;

union1 = test1.logicalor(test2);
union2 = test1.logicalor(test2);
assert(equals(trueunion, union1));
Expand Down

0 comments on commit 0f6f88b

Please sign in to comment.