Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/main/java/com/zaxxer/sparsebits/SparseBitSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -943,8 +943,15 @@ a null area or block, or a clear bit (a set bit in the
if ((a3 = a2[w2]) == null)
break loop;
for (; w3 != LENGTH3; ++w3)
if ((nword = ~a3[w3]) != 0)
{
final long current;
if ((current = ~a3[w3]) != 0)
{
// Only set nword if there was a clear bit in the current word
nword = current;
break loop;
}
}
w3 = 0;
}
w2 = w3 = 0;
Expand Down
142 changes: 142 additions & 0 deletions src/test/java/com/zaxxer/sparsebits/NextClearBitTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package com.zaxxer.sparsebits;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.Rule;
import org.junit.rules.ExpectedException;

public class NextClearBitTest {

SparseBitSet set;

@Rule
public ExpectedException thrown = ExpectedException.none();

@Before
public void setUp() {
set = new SparseBitSet();
}

@Test
public void testNextClearBitAfterFullLastWordInFirstLevel3Entry() {
// The last word in the first level3 block covers bits 1984-2047, set those + the last bit from second
// to last word
for (int i = 1983; i < 2047; i++) {
set.set(i);
}

// Test a known clear bit
Assert.assertEquals(1982, set.nextClearBit(1982));

// Test nextClearBit from the beginning of the last word
Assert.assertEquals(2047, set.nextClearBit(1984));

// Test nextClearBit from the middle of the last word
Assert.assertEquals(2047, set.nextClearBit(2020));

// Test nextClearBit from the end of the last word
Assert.assertEquals(2047, set.nextClearBit(2047));

// Test nextClearBit from the end of the previous word
Assert.assertEquals(2047, set.nextClearBit(1983));

// set the last bit
set.set(2047);
// Test a known clear bit
Assert.assertEquals(1982, set.nextClearBit(1982));

// Test nextClearBit from the beginning of the last word
Assert.assertEquals(2048, set.nextClearBit(1984));

// Test nextClearBit from the middle of the last word
Assert.assertEquals(2048, set.nextClearBit(2020));

// Test nextClearBit from the end of the last word
Assert.assertEquals(2048, set.nextClearBit(2047));

// Test nextClearBit from the end of the previous word
Assert.assertEquals(2048, set.nextClearBit(1983));
}

@Test
public void testNextClearBitAfterFullLastWordInFirstLevel2() {
// The last word in the first level2 covers bits 65472-65535, set those + the last bit from second
// to last word
for (int i = 65471; i < 65535; i++) {
set.set(i);
}

// Set a bit in the third level2 block leaving the second level2 block empty / null.
set.set(65536 * 3 + 1);

// Test a known clear bit
Assert.assertEquals(65470, set.nextClearBit(65470));

// Test nextClearBit from the beginning of the last word
Assert.assertEquals(65535, set.nextClearBit(65472));

// Test nextClearBit from the middle of the last word
Assert.assertEquals(65535, set.nextClearBit(65504));

// Test nextClearBit from the end of the last word
Assert.assertEquals(65535, set.nextClearBit(65535));

// Test nextClearBit from the end of the previous word
Assert.assertEquals(65535, set.nextClearBit(65471));

// set the last bit
set.set(65535);

// Test a known clear bit
Assert.assertEquals(65470, set.nextClearBit(65470));

// Test nextClearBit from the beginning of the last word
Assert.assertEquals(65536, set.nextClearBit(65472));

// Test nextClearBit from the middle of the last word
Assert.assertEquals(65536, set.nextClearBit(65504));

// Test nextClearBit from the end of the last word
Assert.assertEquals(65536, set.nextClearBit(65535));

// Test nextClearBit from the end of the previous word
Assert.assertEquals(65536, set.nextClearBit(65471));
}

@Test
public void testNextClearBitForEmptySet() {
Assert.assertEquals(0, set.nextClearBit(0));
final int x = 65536 * 4 + set.length();
Assert.assertEquals(x, set.nextClearBit(x));
}

@Test
public void testNextClearBitForSingleEntry() {
set.set(50);
Assert.assertEquals(51, set.nextClearBit(50));
}

@Test
public void testNoNextClearBit() {
// Test that nextClearBit returns -1 when there are no clear bits
set.set(Integer.MAX_VALUE - 1);
Assert.assertEquals(-1, set.nextClearBit(Integer.MAX_VALUE - 1));
}

@Test
public void testNegativeIndex() {
// Test that nextClearBit throws an IndexOutOfBoundsException for negative indexes
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage(String.valueOf(-1));
set.nextClearBit(-1);
}

@Test
public void testNegativeIndexLarge() {
// Test with another negative index
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage(String.valueOf(-10000));
set.nextClearBit(-10000);
}
}