Matrix<UpdatableBitArray> matrix6x7 = SMM.newBitMatrix(6, 7);
Matrix<UpdatableBitArray> matrix6x7Save = SMM.newBitMatrix(6, 7);
Matrix<UpdatableBitArray> matrix6x7Work = SMM.newBitMatrix(6, 7);
final UpdatableBitArray array6x7 = matrix6x7.array();
BitArray thinningXPOrXPYP = getThinningXPOrXPYP(matrix6x7);
ConnectedObjectScanner clearer = ConnectedObjectScanner.getBreadthFirstScanner(
matrix6x7Work, ConnectivityType.STRAIGHT_AND_DIAGONAL);
ConnectedObjectScanner.ElementVisitor drawer = new ConnectedObjectScanner.ElementVisitor() {
public void visit(long[] coordinatesInMatrix, long indexInArray) {
array6x7.setBit(indexInArray);
}
};
int bitsFrom = ti << (24 - logCpuCount);
int bitsTo = bitsFrom + (1 << (24 - logCpuCount));
boolean[] centerBitsLocal = new boolean[1 << (24 - logCpuCount)];
for (int bits = bitsFrom; bits < bitsTo; bits++) {
if (exception.get() != null) {
return;
}
array6x7.fill(false);
array6x7.setBit(3 * 6 + 2, true);
int bitIndex = 0;
boolean hasNeighbour = false;
for (int y = 0; y < 5; y++) {
for (int x = 0, disp = (y + 1) * 6; x < 5; x++, disp++) {
if (x == 2 && y == 2) {
continue;
}
boolean b = (bits & 1 << bitIndex) != 0;
if (y >= 1 && y <= 3 && x >= 1 && x <= 3) {
hasNeighbour |= b;
}
array6x7.setBit(disp, b);
bitIndex++;
}
}
assert bitIndex == 24;
boolean centerStaysUnit = thinningXPOrXPYP.getBit(3 * 6 + 2);
centerBitsLocal[bits - bitsFrom] = centerStaysUnit;
if (!centerStaysUnit) {
if (array6x7.getBit(3 * 6 + 1)) {
leftAlwaysZero.set(false);
leftAlwaysZeroViolation.compareAndSet(null,
matrix6x7.matrix(array6x7.updatableClone(Arrays.SMM)));
if (array6x7.getBit(2 * 6 + 1)) {
leftOrLeftTopAlwaysZero.set(false);
leftOrLeftTopAlwaysZeroViolation.compareAndSet(null,
matrix6x7.matrix(array6x7.updatableClone(Arrays.SMM)));
}
if (array6x7.getBit(2 * 6 + 1) || array6x7.getBit(4 * 6 + 1)) {
leftOrLeftPairAlwaysZero.set(false);
leftOrLeftPairAlwaysZeroViolation.compareAndSet(null,
matrix6x7.matrix(array6x7.updatableClone(Arrays.SMM)));
}
}
if (!array6x7.getBit(3 * 6 + 3)) {
rightAlwaysUnit.set(false);
rightAlwaysUnitViolation.compareAndSet(null,
matrix6x7.matrix(array6x7.updatableClone(Arrays.SMM)));
if (hasNeighbour) {
rightAlwaysUnitBesidesIsolatedPixelCase.set(false);
rightAlwaysUnitBesidesIsolatedPixelCaseViolation.compareAndSet(null,
matrix6x7.matrix(array6x7.updatableClone(Arrays.SMM)));
}
}
if (hasNeighbour) {
boolean willHaveRightNeighbour = thinningXPOrXPYP.getBit(3 * 6 + 3);
if (!willHaveRightNeighbour) {
rightAlwaysUnitInSkeleton.set(false);
rightAlwaysUnitInSkeletonViolation.compareAndSet(null,
matrix6x7.matrix(array6x7.updatableClone(Arrays.SMM)));
rightAlwaysUnitInSkeletonViolatingSkeleton.compareAndSet(null,
matrix6x7.matrix(thinningXPOrXPYP.updatableClone(Arrays.SMM)));
boolean hasRightTopNeighbour = array6x7.getBit(2 * 6 + 3);
boolean hasRightBottomNeighbour = array6x7.getBit(4 * 6 + 3);
boolean willHaveRightTopNeighbour = true;
for (int top3Bits = 0; top3Bits < 8; top3Bits++) {
for (int x = 0; x < 3; x++) {
array6x7.setBit(2 + x, (top3Bits & 1 << x) != 0);
}
if (!thinningXPOrXPYP.getBit(2 * 6 + 3)) {
willHaveRightTopNeighbour = false;
break; // save "bad" configuration at finish
}
}
boolean willHaveRightBottomNeighbour = true;
for (int bottom3Bits = 0; bottom3Bits < 8; bottom3Bits++) {
for (int x = 0; x < 3; x++) {
array6x7.setBit(6 * 6 + 2 + x, (bottom3Bits & 1 << x) != 0);
}
if (!thinningXPOrXPYP.getBit(4 * 6 + 3)) {
willHaveRightBottomNeighbour = false;
break; // save "bad" configuration at finish
}
}
if (willHaveRightTopNeighbour && !hasRightTopNeighbour)
throw new AssertionError(String.format(
"ZERO BECOMES UNIT at (3,2):%n%s%nis transformed to%n%s",
AnalyseSkeletonConfigurations.bitMatrixToString(
matrix6x7, 0, 1, 4, 5, 2, 3, " ", true),
AnalyseSkeletonConfigurations.bitMatrixToString(matrix6x7.matrix(
thinningXPOrXPYP), 0, 1, 4, 5, 2, 3, " ", true)));
if (willHaveRightBottomNeighbour && !hasRightBottomNeighbour)
throw new AssertionError(String.format(
"ZERO BECOMES UNIT at (3,4):%n%s%nis transformed to%n%s",
AnalyseSkeletonConfigurations.bitMatrixToString(
matrix6x7, 0, 1, 4, 5, 2, 3, " ", true),
AnalyseSkeletonConfigurations.bitMatrixToString(matrix6x7.matrix(
thinningXPOrXPYP), 0, 1, 4, 5, 2, 3, " ", true)));
// the assertions above are completely verified by VerifySkeletonSymmetry
if (!(willHaveRightTopNeighbour && hasRightBottomNeighbour)) {
rightOrRightTopAlwaysUnitInSkeleton.set(false);
rightOrRightTopAlwaysUnitInSkeletonViolation.compareAndSet(null,
matrix6x7.matrix(array6x7.updatableClone(Arrays.SMM)));
rightOrRightTopAlwaysUnitInSkeletonViolatingSkeleton.compareAndSet(null,
matrix6x7.matrix(thinningXPOrXPYP.updatableClone(Arrays.SMM)));
}
if (!((willHaveRightTopNeighbour && hasRightBottomNeighbour) ||
(willHaveRightBottomNeighbour && hasRightTopNeighbour)))
{
rightInSkeletonOrRightPairAlwaysUnit.set(false);
rightInSkeletonOrRightPairAlwaysUnitViolation.compareAndSet(null,
matrix6x7.matrix(array6x7.updatableClone(Arrays.SMM)));
rightInSkeletonOrRightPairAlwaysUnitViolatingSkeleton.compareAndSet(null,
matrix6x7.matrix(thinningXPOrXPYP.updatableClone(Arrays.SMM)));
}
boolean willHaveBottomNeighbour = true;
if (!willHaveRightTopNeighbour && !willHaveRightBottomNeighbour) {
for (int bottom3Bits = 0; bottom3Bits < 8; bottom3Bits++) {
for (int x = 0; x < 3; x++) {
array6x7.setBit(6 * 6 + 1 + x, (bottom3Bits & 1 << x) != 0);
}
if (!thinningXPOrXPYP.getBit(4 * 6 + 2)) {
willHaveBottomNeighbour = false;
break; // save "bad" configuration at finish
}
}
if (!willHaveBottomNeighbour) {
rightLocality.set(false);
rightLocalityViolation.compareAndSet(null,
matrix6x7.matrix(array6x7.updatableClone(Arrays.SMM)));
rightLocalityViolatingSkeleton.compareAndSet(null,
matrix6x7.matrix(thinningXPOrXPYP.updatableClone(Arrays.SMM)));
}
}
}
}
matrix6x7Save.array().copy(array6x7);
matrix6x7Work.array().copy(array6x7);
array6x7.fill(false);
clearer.clear(null, drawer, 2, 3);
// System.out.printf("%n%s%s",
// AnalyseSkeletonConfigurations.bitMatrixToString(matrix6x7Save,
// 0, 1, 4, 5, 2, 3, " ", true),
// AnalyseSkeletonConfigurations.bitMatrixToString(matrix6x7,
// 0, 1, 4, 5, 2, 3, "> ", true));