| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.lucene.util; |
| |
| import java.util.BitSet; |
| |
| import org.apache.lucene.search.DocIdSetIterator; |
| |
| public class TestOpenBitSet extends LuceneTestCase { |
| |
| void doGet(BitSet a, OpenBitSet b) { |
| int max = a.size(); |
| for (int i=0; i<max; i++) { |
| 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<max; i++) { |
| if (a.get(i) != b.fastGet(i)) { |
| fail("mismatch: BitSet=["+i+"]="+a.get(i)); |
| } |
| if (a.get(i) != b.fastGet((long) i)) { |
| fail("mismatch: BitSet=["+i+"]="+a.get(i)); |
| } |
| } |
| } |
| |
| void doNextSetBit(BitSet a, OpenBitSet b) { |
| int aa=-1,bb=-1; |
| do { |
| aa = a.nextSetBit(aa+1); |
| bb = b.nextSetBit(bb+1); |
| assertEquals(aa,bb); |
| } while (aa>=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; |
| do { |
| // aa = a.prevSetBit(aa-1); |
| aa--; |
| while ((aa >= 0) && (! a.get(aa))) { |
| aa--; |
| } |
| bb = b.prevSetBit(bb-1); |
| assertEquals(aa,bb); |
| } 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); |
| if (mode==2) doIterate2(a, b); |
| } |
| |
| void doIterate1(BitSet a, OpenBitSet b) { |
| int aa=-1,bb=-1; |
| OpenBitSetIterator iterator = new OpenBitSetIterator(b); |
| do { |
| aa = a.nextSetBit(aa+1); |
| bb = random.nextBoolean() ? iterator.nextDoc() : iterator.advance(bb + 1); |
| assertEquals(aa == -1 ? DocIdSetIterator.NO_MORE_DOCS : aa, bb); |
| } while (aa>=0); |
| } |
| |
| void doIterate2(BitSet a, OpenBitSet b) { |
| int aa=-1,bb=-1; |
| OpenBitSetIterator iterator = new OpenBitSetIterator(b); |
| do { |
| aa = a.nextSetBit(aa+1); |
| bb = random.nextBoolean() ? iterator.nextDoc() : iterator.advance(bb + 1); |
| assertEquals(aa == -1 ? DocIdSetIterator.NO_MORE_DOCS : aa, bb); |
| } while (aa>=0); |
| } |
| |
| void doRandomSets(int maxSize, int iter, int mode) { |
| BitSet a0=null; |
| OpenBitSet b0=null; |
| |
| for (int i=0; i<iter; i++) { |
| int sz = random.nextInt(maxSize); |
| BitSet a = new BitSet(sz); |
| OpenBitSet b = new OpenBitSet(sz); |
| |
| // test the various ways of setting bits |
| if (sz>0) { |
| int nOper = random.nextInt(sz); |
| for (int j=0; j<nOper; j++) { |
| int idx; |
| |
| 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); |
| |
| boolean val = b.flipAndGet(idx); |
| 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)); |
| |
| if (!val) b.fastClear(idx); |
| assertTrue(b.get(idx) == val); |
| } |
| } |
| |
| // 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; |
| fromIndex = random.nextInt(sz+80); |
| toIndex = fromIndex + random.nextInt((sz>>1)+1); |
| BitSet aa = (BitSet)a.clone(); aa.flip(fromIndex,toIndex); |
| OpenBitSet bb = (OpenBitSet)b.clone(); bb.flip(fromIndex,toIndex); |
| |
| doIterate(aa,bb, mode); // a problem here is from flip or doIterate |
| |
| fromIndex = random.nextInt(sz+80); |
| toIndex = fromIndex + random.nextInt((sz>>1)+1); |
| 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 |
| 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 |
| doNextSetBitLong(aa,bb); |
| |
| doPrevSetBit(aa,bb); |
| doPrevSetBitLong(aa,bb); |
| |
| if (a0 != null) { |
| assertEquals( a.equals(a0), b.equals(b0)); |
| |
| assertEquals(a.cardinality(), b.cardinality()); |
| |
| BitSet a_and = (BitSet)a.clone(); a_and.and(a0); |
| BitSet a_or = (BitSet)a.clone(); a_or.or(a0); |
| BitSet a_xor = (BitSet)a.clone(); a_xor.xor(a0); |
| BitSet a_andn = (BitSet)a.clone(); a_andn.andNot(a0); |
| |
| OpenBitSet b_and = (OpenBitSet)b.clone(); assertEquals(b,b_and); b_and.and(b0); |
| OpenBitSet b_or = (OpenBitSet)b.clone(); b_or.or(b0); |
| OpenBitSet b_xor = (OpenBitSet)b.clone(); b_xor.xor(b0); |
| OpenBitSet b_andn = (OpenBitSet)b.clone(); b_andn.andNot(b0); |
| |
| doIterate(a_and,b_and, mode); |
| doIterate(a_or,b_or, mode); |
| doIterate(a_xor,b_xor, mode); |
| doIterate(a_andn,b_andn, mode); |
| |
| assertEquals(a_and.cardinality(), b_and.cardinality()); |
| assertEquals(a_or.cardinality(), b_or.cardinality()); |
| assertEquals(a_xor.cardinality(), b_xor.cardinality()); |
| assertEquals(a_andn.cardinality(), b_andn.cardinality()); |
| |
| // test non-mutating popcounts |
| assertEquals(b_and.cardinality(), OpenBitSet.intersectionCount(b,b0)); |
| assertEquals(b_or.cardinality(), OpenBitSet.unionCount(b,b0)); |
| assertEquals(b_xor.cardinality(), OpenBitSet.xorCount(b,b0)); |
| assertEquals(b_andn.cardinality(), OpenBitSet.andNotCount(b,b0)); |
| } |
| |
| a0=a; |
| b0=b; |
| } |
| } |
| |
| // large enough to flush obvious bugs, small enough to run in <.5 sec as part of a |
| // larger testsuite. |
| public void testSmall() { |
| doRandomSets(atLeast(1200), atLeast(1000), 1); |
| doRandomSets(atLeast(1200), atLeast(1000), 2); |
| } |
| |
| // uncomment to run a bigger test (~2 minutes). |
| /* |
| public void testBig() { |
| doRandomSets(2000,200000, 1); |
| doRandomSets(2000,200000, 2); |
| } |
| */ |
| |
| public void testEquals() { |
| OpenBitSet b1 = new OpenBitSet(1111); |
| OpenBitSet b2 = new OpenBitSet(2222); |
| assertTrue(b1.equals(b2)); |
| assertTrue(b2.equals(b1)); |
| b1.set(10); |
| assertFalse(b1.equals(b2)); |
| assertFalse(b2.equals(b1)); |
| b2.set(10); |
| assertTrue(b1.equals(b2)); |
| assertTrue(b2.equals(b1)); |
| b2.set(2221); |
| assertFalse(b1.equals(b2)); |
| assertFalse(b2.equals(b1)); |
| b1.set(2221); |
| assertTrue(b1.equals(b2)); |
| assertTrue(b2.equals(b1)); |
| |
| // try different type of object |
| assertFalse(b1.equals(new Object())); |
| } |
| |
| public void testHashCodeEquals() { |
| OpenBitSet bs1 = new OpenBitSet(200); |
| OpenBitSet bs2 = new OpenBitSet(64); |
| bs1.set(3); |
| bs2.set(3); |
| assertEquals(bs1, bs2); |
| assertEquals(bs1.hashCode(), bs2.hashCode()); |
| } |
| |
| |
| private OpenBitSet makeOpenBitSet(int[] a) { |
| OpenBitSet bs = new OpenBitSet(); |
| for (int e: a) { |
| bs.set(e); |
| } |
| return bs; |
| } |
| |
| private BitSet makeBitSet(int[] a) { |
| BitSet bs = new BitSet(); |
| for (int e: a) { |
| bs.set(e); |
| } |
| return bs; |
| } |
| |
| private void checkPrevSetBitArray(int [] a) { |
| OpenBitSet obs = makeOpenBitSet(a); |
| BitSet bs = makeBitSet(a); |
| doPrevSetBit(bs, obs); |
| } |
| |
| public void testPrevSetBit() { |
| checkPrevSetBitArray(new int[] {}); |
| checkPrevSetBitArray(new int[] {0}); |
| checkPrevSetBitArray(new int[] {0,2}); |
| } |
| } |
| |
| |
| |