implement OpenBitSet.set(from,to) and clear(from,to)

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@549909 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yonik Seeley 2007-06-22 18:00:00 +00:00
parent 02cadd8bb0
commit aa705c5f14
2 changed files with 100 additions and 20 deletions

View File

@ -246,6 +246,35 @@ public class OpenBitSet implements Cloneable, Serializable {
bits[wordNum] |= bitmask;
}
/** Sets a range of bits, expanding the set size if necessary
*
* @param startIndex lower index
* @param endIndex one-past the last bit to set
*/
public void set(long startIndex, long endIndex) {
if (endIndex <= startIndex) return;
int startWord = (int)(startIndex>>6);
// since endIndex is one past the end, this is index of the last
// word to be changed.
int endWord = expandingWordNum(endIndex-1);
long startmask = -1L << startIndex;
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex due to wrap
if (startWord == endWord) {
bits[startWord] |= (startmask & endmask);
return;
}
bits[startWord] |= startmask;
Arrays.fill(bits, startWord+1, endWord, -1L);
bits[endWord] |= endmask;
}
protected int expandingWordNum(long index) {
int wordNum = (int)(index >> 6);
if (wordNum>=wlen) {
@ -283,7 +312,7 @@ public class OpenBitSet implements Cloneable, Serializable {
bits[wordNum] &= ~bitmask;
}
/** clears a bit, allowing access beyond the current set size */
/** clears a bit, allowing access beyond the current set size without changing the size.*/
public void clear(long index) {
int wordNum = (int)(index >> 6); // div 64
if (wordNum>=wlen) return;
@ -292,6 +321,43 @@ public class OpenBitSet implements Cloneable, Serializable {
bits[wordNum] &= ~bitmask;
}
/** Clears a range of bits. Clearing past the end does not change the size of the set.
*
* @param startIndex lower index
* @param endIndex one-past the last bit to clear
*/
public void clear(long startIndex, long endIndex) {
if (endIndex <= startIndex) return;
int startWord = (int)(startIndex>>6);
// since endIndex is one past the end, this is index of the last
// word to be changed.
int endWord = (int)((endIndex-1)>>6);
long startmask = -1L << startIndex;
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex due to wrap
// invert masks since we are clearing
startmask = ~startmask;
endmask = ~endmask;
if (startWord == endWord) {
bits[startWord] &= (startmask | endmask);
return;
}
bits[startWord] &= startmask;
int middle = Math.min(wlen, endWord);
Arrays.fill(bits, startWord+1, middle, 0L);
if (endWord < wlen) {
bits[endWord] &= endmask;
}
}
/** Sets a bit and returns the previous value.
* The index should be less than the OpenBitSet size.
*/
@ -375,22 +441,21 @@ public class OpenBitSet implements Cloneable, Serializable {
if (endIndex <= startIndex) return;
int oldlen = wlen;
ensureCapacity(endIndex);
int startWord = (int)(startIndex>>6);
int endWord = (int)(endIndex>>6);
/*** Grrr, java shifting wraps around so -1L>>64 == -1
// since endIndex is one past the end, this is index of the last
// word to be changed.
int endWord = expandingWordNum(endIndex-1);
/*** Grrr, java shifting wraps around so -1L>>>64 == -1
* for that reason, make sure not to use endmask if the bits to flip will
* be zero in the last word (redefine endWord to be the last changed...)
long startmask = -1L << (startIndex & 0x3f); // example: 11111...111000
long endmask = -1L >>> (64-(endIndex & 0x3f)); // example: 00111...111111
***/
long startmask = -1L << startIndex;
long endmask = (endIndex&0x3f)==0 ? 0 : -1L >>> (64-endIndex);
if (this.wlen <= endWord) {
this.wlen = endWord;
if (endmask!=0) this.wlen++;
}
long endmask = -1L >>> -endIndex; // 64-endIndex is the same as -endIndex due to wrap
if (startWord == endWord) {
bits[startWord] ^= (startmask & endmask);
@ -399,7 +464,7 @@ public class OpenBitSet implements Cloneable, Serializable {
bits[startWord] ^= startmask;
int middle = Math.min(oldlen,endWord);
int middle = Math.min(oldlen, endWord);
for (int i=startWord+1; i<middle; i++) {
bits[i] = ~bits[i];
}
@ -408,9 +473,7 @@ public class OpenBitSet implements Cloneable, Serializable {
Arrays.fill(bits,middle,endWord,-1L);
}
if (endmask!=0) {
bits[endWord] ^= endmask;
}
bits[endWord] ^= endmask;
}

View File

@ -75,7 +75,28 @@ public class TestOpenBitSet extends TestCase {
if (sz>0) {
int nOper = rand.nextInt(sz);
for (int j=0; j<nOper; j++) {
int idx;
int idx;
int idx1,idx2;
idx1 = rand.nextInt(sz);
idx2 = rand.nextInt(sz);
if (idx1>idx2) { idx=idx1; idx1=idx2; idx2=idx; }
a.set(idx1,idx2);
b.set(idx1,idx2);
idx1 = rand.nextInt(sz);
idx2 = rand.nextInt(sz);
if (idx1>idx2) { idx=idx1; idx1=idx2; idx2=idx; }
a.clear(idx1,idx2);
b.clear(idx1,idx2);
idx1 = rand.nextInt(sz);
idx2 = rand.nextInt(sz);
if (idx1>idx2) { idx=idx1; idx1=idx2; idx2=idx; }
a.flip(idx1,idx2);
b.flip(idx1,idx2);
idx = rand.nextInt(sz);
a.set(idx);
b.fastSet(idx);
@ -85,11 +106,6 @@ public class TestOpenBitSet extends TestCase {
idx = rand.nextInt(sz);
a.flip(idx);
b.fastFlip(idx);
int idx1 = rand.nextInt(sz);
int idx2 = rand.nextInt(sz);
if (idx1>idx2) { idx=idx1; idx1=idx2; idx2=idx; }
a.flip(idx1,idx2);
b.flip(idx1,idx2);
boolean val = b.flipAndGet(idx);
boolean val2 = b.flipAndGet(idx);
@ -98,6 +114,7 @@ public class TestOpenBitSet extends TestCase {
val = b.getAndSet(idx);
assertTrue(val2 == val);
assertTrue(b.get(idx));
if (!val) b.fastClear(idx);
assertTrue(b.get(idx) == val);
}