Small optimization to check ranges of bits set in BitArray in bulk

git-svn-id: https://zxing.googlecode.com/svn/trunk@176 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2008-02-12 17:32:15 +00:00
parent 51bb41ed24
commit 9f0cd86114
3 changed files with 67 additions and 14 deletions

View file

@ -73,6 +73,50 @@ public final class BitArray {
}
}
/**
* Efficient method to check if a range of bits is set, or not set.
*
* @param start start of range, inclusive.
* @param end end of range, exclusive
* @param value if true, checks that bits in range are set, otherwise checks that they are not set
* @return true iff all bits are set or not set in range, according to value argument
* @throws IllegalArgumentException if end is less than or equal to start
*/
public boolean isRange(int start, int end, boolean value) {
if (end < start) {
throw new IllegalArgumentException();
}
if (end == start) {
return true; // empty range matches
}
end--; // will be easier to treat this as the last actually set bit -- inclusive
int firstInt = start >> 5;
int lastInt = end >> 5;
for (int i = firstInt; i <= lastInt; i++) {
int firstBit = i > firstInt ? 0 : start & 0x1F;
int lastBit = i < lastInt ? 31 : end & 0x1F;
int mask;
if (firstBit == 0 && lastBit == 31) {
mask = -1;
} else {
mask = 0;
for (int j = firstBit; j <= lastBit; j++) {
mask |= 1 << j;
}
}
if (value) {
if ((bits[i] & mask) != mask) {
return false;
}
} else {
if ((bits[i] & mask) != 0) {
return false;
}
}
}
return true;
}
/**
* @return underlying array of ints. The first element holds the first 32 bits, and the least
* significant bit is bit 0.

View file

@ -82,7 +82,7 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements
nextStart = startRange[1];
// As a check, we want to see some white in front of this "start pattern",
// maybe as wide as the start pattern itself?
foundStart = isWhiteRange(row, Math.max(0, start - 2 * (startRange[1] - start)), start);
foundStart = row.isRange(Math.max(0, start - 2 * (startRange[1] - start)), start, false);
}
return startRange;
}
@ -101,7 +101,7 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements
// Check for whitespace after the pattern
int end = endRange[1];
if (!isWhiteRange(row, end, Math.min(row.getSize(), end + 2 * (end - endRange[0])))) {
if (!row.isRange(end, Math.min(row.getSize(), end + 2 * (end - endRange[0])), false)) {
throw new ReaderException("Pattern not followed by whitespace");
}
@ -115,18 +115,6 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements
new GenericResultPoint((float) (endRange[1] - endRange[0]) / 2.0f, (float) rowNumber)});
}
/**
* @return true iff row consists of white values in the range [start,end)
*/
protected static boolean isWhiteRange(BitArray row, int start, int end) {
for (int i = start; i < end; i++) {
if (row.get(i)) {
return false;
}
}
return true;
}
/**
* Computes the UPC/EAN checksum on a string of digits, and reports
* whether the checksum is correct or not.

View file

@ -63,4 +63,25 @@ public final class BitArrayTestCase extends TestCase {
assertEquals(Integer.MIN_VALUE, ints[1]);
}
public void testIsRange() {
BitArray array = new BitArray(64);
assertTrue(array.isRange(0, 64, false));
assertFalse(array.isRange(0, 64, true));
array.set(32);
assertTrue(array.isRange(32, 33, true));
array.set(31);
assertTrue(array.isRange(31, 33, true));
array.set(34);
assertFalse(array.isRange(31, 35, true));
for (int i = 0; i < 31; i++) {
array.set(i);
}
assertTrue(array.isRange(0, 33, true));
for (int i = 33; i < 64; i++) {
array.set(i);
}
assertTrue(array.isRange(0, 64, true));
assertFalse(array.isRange(0, 64, false));
}
}