Merge "A space-efficient 2D matrix - clean up" into sc-dev

This commit is contained in:
Lee Shombert
2021-06-08 04:02:32 +00:00
committed by Android (Google) Code Review

View File

@@ -67,7 +67,8 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
* <ul> * <ul>
* <li> The matrix does not automatically shrink but there is a compress() method that * <li> The matrix does not automatically shrink but there is a compress() method that
* will recover unused space. * will recover unused space.
* <li> Equality is a very, very expesive operation. * <li> Equality is a very, very expensive operation because it must walk the matrices
* beimg compared element by element.
* </ul> * </ul>
*/ */
@@ -79,10 +80,9 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
static final int STEP = 64; static final int STEP = 64;
/** /**
* There are 8 bits in a byte. The constant is defined here only to make it easy to * The number of bits in the mValues array element.
* find in the code.
*/ */
private static final int BYTE = 8; private static final int PACKING = 32;
/** /**
* Constants that index into the string array returned by matrixToString. The primary * Constants that index into the string array returned by matrixToString. The primary
@@ -123,7 +123,7 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
/** /**
* The boolean array. This array is always {@code mOrder x mOrder} in size. * The boolean array. This array is always {@code mOrder x mOrder} in size.
*/ */
private byte[] mValues; private int[] mValues;
/** /**
* A convenience function called when the elements are added to or removed from the storage. * A convenience function called when the elements are added to or removed from the storage.
@@ -157,10 +157,10 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
throw new RuntimeException("mOrder is " + mOrder + " initCap is " + initialCapacity); throw new RuntimeException("mOrder is " + mOrder + " initCap is " + initialCapacity);
} }
mInUse = new boolean[mOrder]; mInUse = ArrayUtils.newUnpaddedBooleanArray(mOrder);
mKeys = ArrayUtils.newUnpaddedIntArray(mOrder); mKeys = ArrayUtils.newUnpaddedIntArray(mOrder);
mMap = ArrayUtils.newUnpaddedIntArray(mOrder); mMap = ArrayUtils.newUnpaddedIntArray(mOrder);
mValues = new byte[mOrder * mOrder / 8]; mValues = ArrayUtils.newUnpaddedIntArray(mOrder * mOrder / PACKING);
mSize = 0; mSize = 0;
} }
@@ -301,8 +301,8 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
*/ */
private boolean valueAtInternal(int row, int col) { private boolean valueAtInternal(int row, int col) {
int element = row * mOrder + col; int element = row * mOrder + col;
int offset = element / BYTE; int offset = element / PACKING;
int mask = 1 << (element % BYTE); int mask = 1 << (element % PACKING);
return (mValues[offset] & mask) != 0; return (mValues[offset] & mask) != 0;
} }
@@ -324,8 +324,8 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
*/ */
private void setValueAtInternal(int row, int col, boolean value) { private void setValueAtInternal(int row, int col, boolean value) {
int element = row * mOrder + col; int element = row * mOrder + col;
int offset = element / BYTE; int offset = element / PACKING;
byte mask = (byte) (1 << (element % BYTE)); int mask = 1 << (element % PACKING);
if (value) { if (value) {
mValues[offset] |= mask; mValues[offset] |= mask;
} else { } else {
@@ -377,10 +377,10 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
mSize++; mSize++;
// Initialize the row and column corresponding to the new index. // Initialize the row and column corresponding to the new index.
int valueRow = mOrder / BYTE; int valueRow = mOrder / PACKING;
int offset = newIndex / BYTE; int offset = newIndex / PACKING;
byte mask = (byte) (~(1 << (newIndex % BYTE))); int mask = ~(1 << (newIndex % PACKING));
Arrays.fill(mValues, newIndex * valueRow, (newIndex + 1) * valueRow, (byte) 0); Arrays.fill(mValues, newIndex * valueRow, (newIndex + 1) * valueRow, 0);
for (int n = 0; n < mSize; n++) { for (int n = 0; n < mSize; n++) {
mValues[n * valueRow + offset] &= mask; mValues[n * valueRow + offset] &= mask;
} }
@@ -412,25 +412,36 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
* Expand the 2D array. This also extends the free list. * Expand the 2D array. This also extends the free list.
*/ */
private void growMatrix() { private void growMatrix() {
resizeValues(mOrder + STEP); resizeMatrix(mOrder + STEP);
} }
/** /**
* Resize the values array to the new dimension. * Resize the values array to the new dimension.
*/ */
private void resizeValues(int newOrder) { private void resizeMatrix(int newOrder) {
if (newOrder % STEP != 0) {
boolean[] newInuse = Arrays.copyOf(mInUse, newOrder); throw new IllegalArgumentException("matrix order " + newOrder
+ " is not a multiple of " + STEP);
}
int minOrder = Math.min(mOrder, newOrder); int minOrder = Math.min(mOrder, newOrder);
byte[] newValues = new byte[newOrder * newOrder / BYTE]; boolean[] newInUse = ArrayUtils.newUnpaddedBooleanArray(newOrder);
System.arraycopy(mInUse, 0, newInUse, 0, minOrder);
int[] newMap = ArrayUtils.newUnpaddedIntArray(newOrder);
System.arraycopy(mMap, 0, newMap, 0, minOrder);
int[] newKeys = ArrayUtils.newUnpaddedIntArray(newOrder);
System.arraycopy(mKeys, 0, newKeys, 0, minOrder);
int[] newValues = ArrayUtils.newUnpaddedIntArray(newOrder * newOrder / PACKING);
for (int i = 0; i < minOrder; i++) { for (int i = 0; i < minOrder; i++) {
int row = mOrder * i / BYTE; int row = mOrder * i / PACKING;
int newRow = newOrder * i / BYTE; int newRow = newOrder * i / PACKING;
System.arraycopy(mValues, row, newValues, newRow, minOrder / BYTE); System.arraycopy(mValues, row, newValues, newRow, minOrder / PACKING);
} }
mInUse = newInuse; mInUse = newInUse;
mMap = newMap;
mKeys = newKeys;
mValues = newValues; mValues = newValues;
mOrder = newOrder; mOrder = newOrder;
} }
@@ -482,21 +493,21 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
int src = mMap[srcIndex]; int src = mMap[srcIndex];
mInUse[src] = false; mInUse[src] = false;
mMap[srcIndex] = dst; mMap[srcIndex] = dst;
System.arraycopy(mValues, src * mOrder / BYTE, System.arraycopy(mValues, src * mOrder / PACKING,
mValues, dst * mOrder / BYTE, mValues, dst * mOrder / PACKING,
mOrder / BYTE); mOrder / PACKING);
int srcOffset = (src / BYTE); int srcOffset = (src / PACKING);
byte srcMask = (byte) (1 << (src % BYTE)); int srcMask = 1 << (src % PACKING);
int dstOffset = (dst / BYTE); int dstOffset = (dst / PACKING);
byte dstMask = (byte) (1 << (dst % BYTE)); int dstMask = 1 << (dst % PACKING);
for (int i = 0; i < mOrder; i++) { for (int i = 0; i < mOrder; i++) {
if ((mValues[srcOffset] & srcMask) == 0) { if ((mValues[srcOffset] & srcMask) == 0) {
mValues[dstOffset] &= ~dstMask; mValues[dstOffset] &= ~dstMask;
} else { } else {
mValues[dstOffset] |= dstMask; mValues[dstOffset] |= dstMask;
} }
srcOffset += mOrder / BYTE; srcOffset += mOrder / PACKING;
dstOffset += mOrder / BYTE; dstOffset += mOrder / PACKING;
} }
} }
} }
@@ -508,7 +519,7 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
pack(); pack();
int unused = (mOrder - mSize) / STEP; int unused = (mOrder - mSize) / STEP;
if (unused > 0) { if (unused > 0) {
resizeValues(mOrder - (unused * STEP)); resizeMatrix(mOrder - (unused * STEP));
} }
} }