private WAHBitSet genericOp(OpType op, WAHBitSet other) { WAHBitSet ret = new WAHBitSet(); // ensure that they have the same bit length. if (this.numBits() < other.numBits()) { this.setBit(other.numBits() - 1, 0); } else if (this.numBits() > other.numBits()) { other.setBit(numBits() - 1, 0); } if (vec.size() > 0) { run xrun = new run(vec), yrun = new run(other.vec); xrun.decode(); yrun.decode(); do { if (xrun.nWords == 0) { xrun.inc(); xrun.decode(); } if (yrun.nWords == 0) { yrun.inc(); yrun.decode(); } if (xrun.isFill()) { if (yrun.isFill()) { int nWords = Math.min(xrun.nWords, yrun.nWords); ret.appendFill(nWords, getOpResult(op, xrun.fillWord, yrun.fillWord)); xrun.nWords -= nWords; yrun.nWords -= nWords; } else { ret.active.val = getOpResult(op, xrun.fillWord, yrun.get()); ret.appendLiteral(); --xrun.nWords; yrun.nWords = 0; } } else if (yrun.isFill()) { ret.active.val = getOpResult(op, yrun.fillWord, xrun.get()); ret.appendLiteral(); yrun.nWords--; xrun.nWords = 0; } else { ret.active.val = getOpResult(op, xrun.get(), yrun.get()); ret.appendLiteral(); yrun.nWords = 0; xrun.nWords = 0; } } while (!(xrun.end() && yrun.end())); } ret.active.val = getOpResult(op, this.active.val, other.active.val); ret.active.nbits = this.active.nbits; ret.doCount(); return ret; }
private void appendWord(int w) { if (RUN_UNTESTED_CODE) { int nb1, nb2; int cps = (w >>> MAXBITS); nset = 0; if (active.nbits != 0) { // active contains some uncompressed bits int w1; nb1 = active.nbits; nb2 = MAXBITS - active.nbits; active.val <<= nb2; if (cps != 0) { // incoming bits are comporessed boolean b2 = isOneFill(w); if (b2) { w1 = (1 << nb2) - 1; active.val |= w1; } appendLiteral(); nb2 = (w & MAXCNT) - 1; if (nb2 > 1) { // append a counter appendCounter(b2 ? 1 : 0, nb2); } else if (nb2 == 1) { if (b2) active.val = ALLONES; appendLiteral(); } active.nbits = nb1; active.val = ((1 << nb1) - 1) * (b2 ? 1 : 0); } else { // incoming bits are not compressed w1 = (w >>> nb1); active.val |= w1; appendLiteral(); w1 = (1 << nb1) - 1; active.val = (w & w1); active.nbits = nb1; } } // end of the case where there are active bits else if (cps != 0) { // no active bit int b2 = (isOneFill(w) ? 1 : 0); nb2 = (w & MAXCNT); if (nb2 > 1) appendCounter(b2, nb2); else if (nb2 == 1) { if (b2 != 0) active.val = ALLONES; appendLiteral(); } } else { // no active bits // new word is a raw bit pattern, simply add the word active.val = w; appendLiteral(); } } else { throw new AssertionError("Untested code detected, would rather die than run this"); } }
private void appendFill(int nWords, int v) { if (vec.isEmpty()) { if (v == 0) { vec.add(HEADER0 | nWords); } else { vec.add(HEADER1 | nWords); } } else if (nWords > 1) { int back = getBack(); if (v == 0) { if (isZeroFill(back)) { setBack(back + nWords); } else { vec.add(HEADER0 | nWords); } } else if (isOneFill(back)) { setBack(back + nWords); } else { vec.add(HEADER1 | nWords); } } else { active.val = v != 0 ? ALLONES : 0; appendLiteral(); } }
private void setBit(int ind, int val) { assert val == 0 || val == 1; if (ind >= numBits()) { int diff = ind - numBits() + 1; if (active.nbits > 0) { if (ind + 1 >= nbits + MAXBITS) { diff -= MAXBITS - active.nbits; active.val <<= (MAXBITS - active.nbits); if (diff == 0) active.val += (val != 0 ? 1 : 0); appendLiteral(); } else { active.nbits += diff; active.val <<= diff; active.val += (val != 0 ? 1 : 0); diff = 0; } } if (diff != 0) { int w = diff / MAXBITS; diff -= w * MAXBITS; if (diff != 0) { if (w > 1) { appendCounter(0, w); } else if (w != 0) { appendLiteral(); } active.nbits = diff; active.val += (val != 0 ? 1 : 0); } else if (val != 0) { if (w > 2) { appendCounter(0, w - 1); } else if (w == 2) { appendLiteral(); } active.val = 1; appendLiteral(); } else { if (w > 1) { appendCounter(0, w); } else if (w != 0) { appendLiteral(); } } } if (numBits() != ind + 1) logger.warning("Warning"); if (nset != 0) nset += (val != 0 ? 1 : 0); return; } else if (ind >= nbits) { // modify an active bit int u = active.val; if (val != 0) { active.val |= (1 << (active.nbits - (ind - nbits) - 1)); } else { active.val &= ~(1 << (active.nbits - (ind - nbits) - 1)); } if (nset != 0 && (u != active.val)) nset += (val != 0 ? 1 : -1); return; } else if (vec.size() * MAXBITS == nbits) { // uncompressed int i = ind / MAXBITS; int u = vec.get(i); int w = (1 << (SECONDBIT - (ind % MAXBITS))); if (val != 0) vec.setQuick(i, u |= w); else vec.setQuick(i, u &= ~w); if (nset != 0 && (vec.getQuick(i) != u)) nset += (val != 0 ? 1 : -1); return; } // the code after this has not been verified at all... // should proceed with caution. // compressed bit vector -- // the bit to be modified is in vec if (RUN_UNTESTED_CODE) { int idx = 0; int compressed = 0, cnt = 0, ind1 = 0, ind0 = ind; int current = 0; // current bit value while ((ind0 > 0) && (idx < vec.size())) { int v = vec.getQuick(idx); if (isAFill(v)) { // a fill cnt = ((v) & MAXCNT) * MAXBITS; if (cnt > ind0) { // found the location current = (isOneFill(v) ? 1 : 0); compressed = 1; ind1 = ind0; ind0 = 0; } else { ind0 -= cnt; ind1 = ind0; ++idx; } } else { // a literal word cnt = MAXBITS; if (MAXBITS > ind0) { // found the location current = (1 & ((v) >>> (SECONDBIT - ind0))); compressed = 0; ind1 = ind0; ind0 = 0; } else { ind0 -= MAXBITS; ind1 = ind0; ++idx; } } } // while (ind... if (ind1 == 0) { // set current and compressed int v = vec.getQuick(idx); if (isAFill(v)) { cnt = (v & MAXCNT) * MAXBITS; current = (isOneFill(v) ? 1 : 0); compressed = 1; } else { cnt = MAXBITS; current = (v >>> SECONDBIT); compressed = 0; } } if (ind0 > 0) // has not found the right location yet. { if (ind0 < active.nbits) { // in the active word ind1 = (1 << (active.nbits - ind0 - 1)); if (val != 0) { active.val |= ind1; } else { active.val &= ~ind1; } } else { // extends the current bit vector ind1 = ind0 - active.nbits - 1; appendWord(HEADER0 | (ind1 / MAXBITS)); for (ind1 %= MAXBITS; ind1 > 0; --ind1) addOneBit(0); addOneBit(val != 0 ? 1 : 0); } if (nset != 0) nset += val != 0 ? 1 : -1; return; } // locate the bit to be changed, lots of work hidden here if (current == val) return; // nothing to do int v = vec.getQuick(idx); // need to actually modify the bit if (compressed == 0) { // toggle a single bit of a literal word v ^= (1 << (SECONDBIT - ind1)); vec.setQuick(idx, v); } else if (ind1 < MAXBITS) { // bit to be modified is in the first word, two pieces --v; vec.set(idx, v); if ((v & MAXCNT) == 1) { v = (current != 0) ? ALLONES : 0; vec.setQuick(idx, v); } int w = 1 << (SECONDBIT - ind1); if (val == 0) w ^= ALLONES; vec.beforeInsert(idx, w); idx++; } else if (cnt - ind1 <= MAXBITS) { // bit to be modified is in the last word, two pieces --(v); vec.setQuick(idx, v); if ((v & MAXCNT) == 1) { v = (current != 0) ? ALLONES : 0; vec.setQuick(idx, v); } int w = 1 << (cnt - ind1 - 1); if (val == 0) w ^= ALLONES; ++idx; vec.beforeInsert(idx, w); } else { // the counter breaks into three pieces int u[] = new int[2], w; u[0] = ind1 / MAXBITS; w = (v & MAXCNT) - u[0] - 1; u[1] = 1 << (SECONDBIT - ind1 + u[0] * MAXBITS); if (val == 0) { u[0] = (u[0] > 1) ? (HEADER1 | u[0]) : (ALLONES); u[1] ^= ALLONES; w = (w > 1) ? (HEADER1 | w) : (ALLONES); } else { u[0] = (u[0] > 1) ? (HEADER0 | u[0]) : 0; w = (w > 1) ? (HEADER0 | w) : 0; } vec.setQuick(idx, w); vec.beforeInsertAllOf(idx, Arrays.asList(u)); } if (nset != 0) nset += val != 0 ? 1 : -1; } else { throw new AssertionError("Untested code detected, would rather die than run this"); } }
/** * Returns a new WAH compressed bitset after anding the current bitset with the <i>other</i> * bitset. * * @param other the bitset to and with * @return The resulting bitset */ public WAHBitSet and(WAHBitSet other) { WAHBitSet ret = new WAHBitSet(); // ensure that they have the same bit length. if (this.numBits() < other.numBits()) { this.setBit(other.numBits() - 1, 0); } else if (this.numBits() > other.numBits()) { other.setBit(numBits() - 1, 0); } // if there is something in the vector. if (vec.size() > 0) { // create new run objects and decode them. run xrun = new run(vec), yrun = new run(other.vec); xrun.decode(); yrun.decode(); do { // if you finished a run, then get the next one. if (xrun.nWords == 0) { xrun.inc(); xrun.decode(); } if (yrun.nWords == 0) { yrun.inc(); yrun.decode(); } if (xrun.isFill()) { if (yrun.isFill()) { // both are fills... this is the best. int nWords = Math.min(xrun.nWords, yrun.nWords); ret.appendFill(nWords, xrun.fillWord & yrun.fillWord); xrun.nWords -= nWords; yrun.nWords -= nWords; } else { // just cut through the other run chewUpRun(xrun, ret, yrun); } } else if (yrun.isFill()) { // again do the same, with different order. chewUpRun(yrun, ret, xrun); } else { // both are literals, so get the new literal and // append it to the return value. ret.active.val = xrun.get() & yrun.get(); ret.appendLiteral(); yrun.nWords = 0; xrun.nWords = 0; } // till they are not at the end. } while (!(xrun.end() && yrun.end())); } // set the active word. ret.active.val = this.active.val & other.active.val; ret.active.nbits = this.active.nbits; // ensure that the counts are set properly. ret.doCount(); return ret; }