introduce bitloops

This commit is contained in:
mike
2026-01-14 13:12:21 +01:00
parent 0b7a59b769
commit b1f54c2cae
2 changed files with 90 additions and 81 deletions

View File

@@ -57,6 +57,8 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
static final int SIZE = C * R;// ~18
static final int SIZE_MIN_1 = SIZE - 1;// ~18
static final double SIZED = (double) SIZE;// ~18
static final long MASK_LO = (SIZE >= 64) ? -1L : (1L << SIZE) - 1;
static final long MASK_HI = (SIZE <= 64) ? 0L : (SIZE >= 128 ? -1L : (1L << (SIZE - 64)) - 1);
static final int TARGET_CLUES = SIZE >>> 2;
static final int MAX_WORD_LENGTH = C <= R ? C : R;
static final int MAX_WORD_LENGTH_PLUS_ONE = MAX_WORD_LENGTH + 1;
@@ -249,15 +251,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
long matchLo = (~(lo ^ b.lo)) & (~lo | (~(vlo ^ b.vlo) & ~(rlo ^ b.rlo)));
long matchHi = (~(hi ^ b.hi)) & (~hi | (~(vhi ^ b.vhi) & ~(rhi ^ b.rhi)));
long maskLo = (SIZE >= 64) ? -1L : (1L << SIZE) - 1;
long maskHi = (SIZE <= 64) ? 0L : (1L << (SIZE - 64)) - 1;
return (Long.bitCount(matchLo & maskLo) + Long.bitCount(matchHi & maskHi)) / SIZED;
/* var same = 0;
for (int i = 0; i < SIZE; i++) if (digitAt(i) == b.digitAt(i)) same++;
return same / SIZED;*/
return (Long.bitCount(matchLo & MASK_LO) + Long.bitCount(matchHi & MASK_HI)) / SIZED;
}
public Grid toGrid() { return new Grid(new byte[SIZE], lo, hi); }
public void forEachSlot(SlotVisitor visitor) {
@@ -452,49 +446,78 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
long penalty = (((long) Math.abs(grid.clueCount() - TARGET_CLUES)) * 16000L);
boolean hasSlots = false;
for (int i = 0; i < 65; i += 64) {
for (long bits = (i == 0 ? lo_cl : hi_cl); bits != X; bits &= bits - 1) {
int clueIdx = i | Long.numberOfTrailingZeros(bits);
int key = Slot.packSlotDir(clueIdx, grid.digitAt(clueIdx));
/// long clueBits = (i == 0 ? lo_cl : hi_cl);
/// long vBits = (i == 0 ? grid.vlo : grid.vhi);
/// long rBits = (i == 0 ? grid.rlo : grid.rhi);
/// for (long bits = clueBits; bits != X; bits &= bits - 1) {
/// long lsb = bits & -bits;
/// int clueIdx = i | Long.numberOfTrailingZeros(lsb);
/// int v = (vBits & lsb) != 0 ? 1 : 0;
/// int r = (rBits & lsb) != 0 ? 1 : 0;
/// int key = Slot.packSlotDir(clueIdx, (r << 1) | v);
long rLo = PATH_LO[key], rHi = PATH_HI[key];
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
if (Slot.increasing(key)) {
if (hLo != X) {
rLo &= ((1L << Long.numberOfTrailingZeros(hLo)) - 1);
rHi = 0;
} else if (hHi != X) { rHi &= ((1L << Long.numberOfTrailingZeros(hHi)) - 1); }
} else {
if (hHi != X) {
int msb = 63 - Long.numberOfLeadingZeros(hHi);
rHi &= ~((1L << msb << 1) - 1);
rLo = 0;
} else if (hLo != X) {
int msb = 63 - Long.numberOfLeadingZeros(hLo);
rLo &= ~((1L << msb << 1) - 1);
}
for (long bits = lo_cl; bits != X; bits &= bits - 1) {
long lsb = bits & -bits;
int clueIdx = Long.numberOfTrailingZeros(lsb);
int v = (grid.vlo & lsb) != 0 ? 1 : 0;
int r = (grid.rlo & lsb) != 0 ? 1 : 0;
int key = Slot.packSlotDir(clueIdx, (r << 1) | v);
long rLo = PATH_LO[key], rHi = PATH_HI[key];
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
if (Slot.increasing(key)) {
if (hLo != X) {
rLo &= ((1L << Long.numberOfTrailingZeros(hLo)) - 1);
rHi = 0;
} else if (hHi != X) { rHi &= ((1L << Long.numberOfTrailingZeros(hHi)) - 1); }
} else {
if (hHi != X) {
int msb = 63 - Long.numberOfLeadingZeros(hHi);
rHi &= ~((1L << msb << 1) - 1);
rLo = 0;
} else if (hLo != X) {
int msb = 63 - Long.numberOfLeadingZeros(hLo);
rLo &= ~((1L << msb << 1) - 1);
}
if ((rLo | rHi) != X) {
hasSlots = true;
if (Slot.horiz(key)) {
cHLo |= rLo;
cHHi |= rHi;
} else {
cVLo |= rLo;
cVHi |= rHi;
}
if ((Long.bitCount(rLo) + Long.bitCount(rHi)) < MIN_LEN) penalty += 8000;
}
if ((rLo | rHi) != X) {
hasSlots = true;
if (Slot.horiz(key)) {
cHLo |= rLo;
cHHi |= rHi;
} else {
penalty += 25000;
cVLo |= rLo;
cVHi |= rHi;
}
if ((Long.bitCount(rLo) + Long.bitCount(rHi)) < MIN_LEN) penalty += 8000;
} else {
penalty += 25000;
}
}
for (long bits = hi_cl; bits != X; bits &= bits - 1) {
long lsb = bits & -bits;
int clueIdx = Long.numberOfTrailingZeros(lsb);
int v = (grid.vhi & lsb) != 0 ? 1 : 0;
int r = (grid.rhi & lsb) != 0 ? 1 : 0;
int key = Slot.packSlotDir(64 | clueIdx, (r << 1) | v);
long rLo = PATH_LO[key], rHi = PATH_HI[key];
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
if (Slot.increasing(key)) {
if (hLo != X) {
rLo &= ((1L << Long.numberOfTrailingZeros(hLo)) - 1);
rHi = 0;
} else if (hHi != X) { rHi &= ((1L << Long.numberOfTrailingZeros(hHi)) - 1); }
} else {
if (hHi != X) {
int msb = 63 - Long.numberOfLeadingZeros(hHi);
rHi &= ~((1L << msb << 1) - 1);
rLo = 0;
} else if (hLo != X) {
int msb = 63 - Long.numberOfLeadingZeros(hLo);
rLo &= ~((1L << msb << 1) - 1);
}
}
if ((rLo | rHi) != X) {
hasSlots = true;
if (Slot.horiz(key)) {
cHLo |= rLo;
cHHi |= rHi;
} else {
cVLo |= rLo;
cVHi |= rHi;
}
if ((Long.bitCount(rLo) + Long.bitCount(rHi)) < MIN_LEN) penalty += 8000;
} else {
penalty += 25000;
}
}
@@ -614,35 +637,21 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
var nc = Math.cos(theta);
var nr = Math.sin(theta);
long maskLo = 0, maskHi = 0;
for (var rci : IT) {
int i = rci.i();
if ((rci.cross_r()) * nc + (rci.cross_c()) * nr < 0) {
var ch = other.digitAt(i);
if (out.digitAt(i) != ch) {
if (other.isClue(i)) {
out.setClue(i, ch);
} else {
out.clearClue(i);
}
}
int i = rci.i();
if ((i & 64) == 0) maskLo |= (1L << i);
else maskHi |= (1L << (i - 64));
}
}
// long maskLo = 0, maskHi = 0;
// for (var rci : IT) {
// if ((rci.cross_r()) * nc + (rci.cross_c()) * nr < 0) {
// int i = rci.i();
// if (i < 64) maskLo |= (1L << i);
// else maskHi |= (1L << (i - 64));
// }
// }
//
// out.lo = (out.lo & ~maskLo) | (other.lo & maskLo);
// out.hi = (out.hi & ~maskHi) | (other.hi & maskHi);
// out.vlo = (out.vlo & ~maskLo) | (other.vlo & maskLo);
// out.vhi = (out.vhi & ~maskHi) | (other.vhi & maskHi);
// out.rlo = (out.rlo & ~maskLo) | (other.rlo & maskLo);
// out.rhi = (out.rhi & ~maskHi) | (other.rhi & maskHi);
out.lo = (out.lo & ~maskLo) | (other.lo & maskLo);
out.hi = (out.hi & ~maskHi) | (other.hi & maskHi);
out.vlo = (out.vlo & ~maskLo) | (other.vlo & maskLo);
out.vhi = (out.vhi & ~maskHi) | (other.vhi & maskHi);
out.rlo = (out.rlo & ~maskLo) | (other.rlo & maskLo);
out.rhi = (out.rhi & ~maskHi) | (other.rhi & maskHi);
for (var lo = out.lo; lo != X; lo &= lo - 1L) clearClues(out, Long.numberOfTrailingZeros(lo));
for (var hi = out.hi; hi != X; hi &= hi - 1L) clearClues(out, 64 | Long.numberOfTrailingZeros(hi));

View File

@@ -162,14 +162,14 @@ public class MainTest {
var mask = swe.generateMask(opts.pop, opts.gens, Math.max(opts.pop, (int) Math.floor(opts.pop * 1.5)));
val clued = new Clued(mask);
val test = clued.gridToString();
val RESULT = " 3 300\n" +
" 1 \n" +
" 1 \n" +
" 3 0 \n" +
" 31 \n" +
" 1 \n" +
" 1 2\n" +
"21 22 3";
val RESULT = "001 \n" +
" 3 3\n" +
" 3\n" +
" 3\n" +
" 21 1 \n" +
" 3 \n" +
"221 1 \n" +
"1 22";
Assertions.assertEquals(18, clued.clueCount(), "Found seed changed");
Assertions.assertEquals(RESULT, test, "Found seed changed");