From bec184fa397b512dfd1189ab5ac7fa751abfdc98 Mon Sep 17 00:00:00 2001 From: Uwe Schindler Date: Wed, 6 Jul 2011 20:43:55 +0000 Subject: [PATCH] LUCENE-3179: Add missing long methods and add good tests for uncovered code. The cutover to Long.numberOfLeadingZeroes was not done, see issue comment. git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1143558 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/lucene/util/OpenBitSet.java | 33 +++++++++ .../apache/lucene/util/TestOpenBitSet.java | 67 ++++++++++++++++++- 2 files changed, 97 insertions(+), 3 deletions(-) diff --git a/lucene/src/java/org/apache/lucene/util/OpenBitSet.java b/lucene/src/java/org/apache/lucene/util/OpenBitSet.java index 67965206a51..fadb19955e1 100644 --- a/lucene/src/java/org/apache/lucene/util/OpenBitSet.java +++ b/lucene/src/java/org/apache/lucene/util/OpenBitSet.java @@ -692,6 +692,39 @@ public class OpenBitSet extends DocIdSet implements Bits, Cloneable { return -1; } + /** Returns the index of the first set bit starting downwards at + * the index specified. + * -1 is returned if there are no more set bits. + */ + public long prevSetBit(long index) { + int i = (int) (index >> 6); + final int subIndex; + long word; + if (i >= wlen) { + i = wlen - 1; + if (i < 0) return -1; + subIndex = 63; // last possible bit + word = bits[i]; + } else { + if (i < 0) return -1; + subIndex = (int)index & 0x3f; // index within the word + word = (bits[i] << (63-subIndex)); // skip all the bits to the left of index + } + + if (word != 0) { + return (((long)i)<<6) + subIndex - Long.numberOfLeadingZeros(word); // See LUCENE-3197 + } + + while (--i >= 0) { + word = bits[i]; + if (word !=0 ) { + return (((long)i)<<6) + 63 - Long.numberOfLeadingZeros(word); + } + } + + return -1; + } + @Override public Object clone() { try { diff --git a/lucene/src/test/org/apache/lucene/util/TestOpenBitSet.java b/lucene/src/test/org/apache/lucene/util/TestOpenBitSet.java index 61322fe67c2..b487a588440 100644 --- a/lucene/src/test/org/apache/lucene/util/TestOpenBitSet.java +++ b/lucene/src/test/org/apache/lucene/util/TestOpenBitSet.java @@ -29,6 +29,20 @@ public class TestOpenBitSet extends LuceneTestCase { if (a.get(i) != b.get(i)) { fail("mismatch: BitSet=["+i+"]="+a.get(i)); } + if (a.get(i) != b.get((long) i)) { + fail("mismatch: BitSet=["+i+"]="+a.get(i)); + } + } + } + + void doGetFast(BitSet a, OpenBitSet b, int max) { + for (int i=0; i=0); } + void doNextSetBitLong(BitSet a, OpenBitSet b) { + int aa=-1,bb=-1; + do { + aa = a.nextSetBit(aa+1); + bb = (int) b.nextSetBit((long) (bb+1)); + assertEquals(aa,bb); + } while (aa>=0); + } + void doPrevSetBit(BitSet a, OpenBitSet b) { int aa = a.size() + random.nextInt(100); int bb = aa; @@ -55,6 +78,20 @@ public class TestOpenBitSet extends LuceneTestCase { } while (aa>=0); } + void doPrevSetBitLong(BitSet a, OpenBitSet b) { + int aa = a.size() + random.nextInt(100); + int bb = aa; + do { + // aa = a.prevSetBit(aa-1); + aa--; + while ((aa >= 0) && (! a.get(aa))) { + aa--; + } + bb = (int) b.prevSetBit((long) (bb-1)); + assertEquals(aa,bb); + } while (aa>=0); + } + // test interleaving different OpenBitSetIterator.next()/skipTo() void doIterate(BitSet a, OpenBitSet b, int mode) { if (mode==1) doIterate1(a, b); @@ -99,9 +136,19 @@ public class TestOpenBitSet extends LuceneTestCase { idx = random.nextInt(sz); a.set(idx); b.fastSet(idx); + + idx = random.nextInt(sz); + a.set(idx); + b.fastSet((long) idx); + idx = random.nextInt(sz); a.clear(idx); b.fastClear(idx); + + idx = random.nextInt(sz); + a.clear(idx); + b.fastClear((long) idx); + idx = random.nextInt(sz); a.flip(idx); b.fastFlip(idx); @@ -110,6 +157,14 @@ public class TestOpenBitSet extends LuceneTestCase { boolean val2 = b.flipAndGet(idx); assertTrue(val != val2); + idx = random.nextInt(sz); + a.flip(idx); + b.fastFlip((long) idx); + + val = b.flipAndGet((long) idx); + val2 = b.flipAndGet((long) idx); + assertTrue(val != val2); + val = b.getAndSet(idx); assertTrue(val2 == val); assertTrue(b.get(idx)); @@ -121,6 +176,7 @@ public class TestOpenBitSet extends LuceneTestCase { // test that the various ways of accessing the bits are equivalent doGet(a,b); + doGetFast(a, b, sz); // test ranges, including possible extension int fromIndex, toIndex; @@ -136,17 +192,22 @@ public class TestOpenBitSet extends LuceneTestCase { aa = (BitSet)a.clone(); aa.clear(fromIndex,toIndex); bb = (OpenBitSet)b.clone(); bb.clear(fromIndex,toIndex); - doNextSetBit(aa,bb); // a problem here is from clear() or nextSetBit + doNextSetBit(aa,bb); // a problem here is from clear() or nextSetBit + doNextSetBitLong(aa,bb); + doPrevSetBit(aa,bb); + doPrevSetBitLong(aa,bb); fromIndex = random.nextInt(sz+80); toIndex = fromIndex + random.nextInt((sz>>1)+1); aa = (BitSet)a.clone(); aa.set(fromIndex,toIndex); bb = (OpenBitSet)b.clone(); bb.set(fromIndex,toIndex); - doNextSetBit(aa,bb); // a problem here is from set() or nextSetBit + doNextSetBit(aa,bb); // a problem here is from set() or nextSetBit + doNextSetBitLong(aa,bb); + doPrevSetBit(aa,bb); - + doPrevSetBitLong(aa,bb); if (a0 != null) { assertEquals( a.equals(a0), b.equals(b0));