Skip to content

Commit

Permalink
Small BitSet fixes and improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Ihromant committed Sep 9, 2024
1 parent 59259c3 commit 045ebdf
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 9 deletions.
43 changes: 34 additions & 9 deletions classlib/src/main/java/org/teavm/classlib/java/util/TBitSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
import java.util.function.IntPredicate;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.lang.*;
import org.teavm.classlib.java.nio.TByteBuffer;
import org.teavm.classlib.java.nio.TByteOrder;
import org.teavm.classlib.java.nio.TLongBuffer;
import org.teavm.classlib.java.util.stream.TIntStream;
import org.teavm.classlib.java.util.stream.intimpl.TSimpleIntStreamImpl;
import org.teavm.interop.Rename;
Expand Down Expand Up @@ -52,6 +55,13 @@ public static TBitSet valueOf(long[] longs) {
return new TBitSet(ints);
}

public static TBitSet valueOf(TLongBuffer buff) {
buff = buff.slice();
long[] words = new long[buff.remaining()];
buff.get(words);
return valueOf(words);
}

public static TBitSet valueOf(byte[] bytes) {
int[] ints = new int[(bytes.length + 3) / 4];
int fullInts = bytes.length / 4;
Expand All @@ -76,12 +86,19 @@ public static TBitSet valueOf(byte[] bytes) {
return new TBitSet(ints);
}

public static TBitSet valueOf(TByteBuffer buff) {
buff = buff.slice().order(TByteOrder.LITTLE_ENDIAN);
byte[] words = new byte[buff.remaining()];
buff.get(words);
return valueOf(words);
}

public byte[] toByteArray() {
byte[] bytes = new byte[(length + 7) / 8];
int fullInts = length / TInteger.SIZE;
int fullInts = bytes.length / 4;
int j = 0;
int i = 0;
for (; i < fullInts; i += 4) {
for (; i < fullInts; i++) {
bytes[j++] = (byte) data[i];
bytes[j++] = (byte) (data[i] >>> 8);
bytes[j++] = (byte) (data[i] >>> 16);
Expand Down Expand Up @@ -348,8 +365,12 @@ public int nextClearBit(int fromIndex) {
}

public int previousSetBit(int fromIndex) {
if (fromIndex == -1) {
return -1;
if (fromIndex < 0) {
if (fromIndex == -1) {
return -1;
} else {
throw new IndexOutOfBoundsException();
}
}
if (fromIndex >= length) {
fromIndex = length;
Expand All @@ -360,7 +381,7 @@ public int previousSetBit(int fromIndex) {
if (val != 0) {
return fromIndex - TInteger.numberOfLeadingZeros(val);
}
for (int i = index - 1; i >= 0; ++i) {
for (int i = index - 1; i >= 0; --i) {
if (data[i] != 0) {
return (i + 1) * 32 - TInteger.numberOfLeadingZeros(data[i]) - 1;
}
Expand All @@ -369,8 +390,12 @@ public int previousSetBit(int fromIndex) {
}

public int previousClearBit(int fromIndex) {
if (fromIndex == -1) {
return -1;
if (fromIndex < 0) {
if (fromIndex == -1) {
return -1;
} else {
throw new IndexOutOfBoundsException();
}
}
if (fromIndex >= length) {
return fromIndex;
Expand All @@ -381,7 +406,7 @@ public int previousClearBit(int fromIndex) {
if (val != 0) {
return fromIndex - TInteger.numberOfLeadingZeros(val);
}
for (int i = index - 1; i >= 0; ++i) {
for (int i = index - 1; i >= 0; --i) {
if (data[i] != 0xFFFFFFFF) {
return (i + 1) * 32 - TInteger.numberOfLeadingZeros(~data[i]) - 1;
}
Expand Down Expand Up @@ -425,7 +450,7 @@ public boolean intersects(TBitSet set) {

public int cardinality() {
int result = 0;
int sz = 1 + length / 32;
int sz = (length + 31) / 32;
for (int i = 0; i < sz; ++i) {
result += TInteger.bitCount(data[i]);
}
Expand Down
28 changes: 28 additions & 0 deletions tests/src/test/java/org/teavm/classlib/java/util/BitSetTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ public void constructFromBytes() {
}
}

@Test
public void toByteArray() throws Exception {
assertEquals("[]", Arrays.toString(BitSet.valueOf(new long[0]).toByteArray()));
assertEquals("[1]", Arrays.toString(BitSet.valueOf(new long[] { 1 }).toByteArray()));
assertEquals("[-17, -51, -85, -112, 120, 86, 52, 18]",
Arrays.toString(BitSet.valueOf(new long[] { 0x1234567890abcdefL }).toByteArray()));
assertEquals("[1, 0, 0, 0, 0, 0, 0, 0, 2]",
Arrays.toString(BitSet.valueOf(new long[] { 1, 2 }).toByteArray()));
}

@Test
public void constructFromLongs() {
BitSet bs = BitSet.valueOf(new long[] { 7, 2, 5, 1L << 36 });
Expand Down Expand Up @@ -1225,6 +1235,10 @@ public void cardinality() {

bs.set(0, 500);
assertEquals("cardinality() returned wrong value", 500, bs.cardinality());

bs = new BitSet();
bs.set(31);
assertEquals(1, bs.cardinality());
}

@Test
Expand All @@ -1251,6 +1265,20 @@ public void previousSetBitFound() {
assertEquals(2, bs.previousSetBit(2));
assertEquals(-1, bs.previousSetBit(1));
assertEquals(-1, bs.previousSetBit(0));
bs = new BitSet();
bs.set(0);
bs.set(1);
bs.set(32);
bs.set(192);
bs.set(666);
assertEquals(666, bs.previousSetBit(999));
assertEquals(666, bs.previousSetBit(667));
assertEquals(666, bs.previousSetBit(666));
assertEquals(192, bs.previousSetBit(665));
assertEquals(32, bs.previousSetBit(191));
assertEquals(1, bs.previousSetBit(31));
assertEquals(0, bs.previousSetBit(0));
assertEquals(-1, bs.previousSetBit(-1));
}

@Test
Expand Down

0 comments on commit 045ebdf

Please sign in to comment.