introduce bitloops

This commit is contained in:
mike
2026-01-14 11:37:40 +01:00
parent c1706e1bf7
commit 8e049b3fa5
3 changed files with 62 additions and 65 deletions

View File

@@ -441,7 +441,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
}
visitor.visit(key, rayLo, rayHi);
//if ((rayLo | rayHi) == 0L) throw new RuntimeException()
}
static Slot[] extractSlots(Clues grid) {
@@ -733,37 +732,38 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
return best.grid;
}
static long patternForSlot(Grid grid, Slot s) {
if ((s.lo & grid.lo) == 0 && (s.hi & grid.hi) == 0) {
static long patternForSlot(Grid grid, final int key, final long lo, final long hi) {
final long glo = grid.lo, ghi = grid.hi;
if ((lo & glo) == 0 && (hi & ghi) == 0) {
return 0;
}
long p = 0;
if (s.increasing()) {
for (long b = s.lo & grid.lo; b != 0; b &= b - 1) {
if (Slot.increasing(key)) {
for (long b = lo & glo; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
byte val = grid.g[idx];
int i = Long.bitCount(s.lo & ((1L << idx) - 1));
int i = Long.bitCount(lo & ((1L << idx) - 1));
p |= ((long) (i * 26 + val)) << (i << 3);
}
int offset = Long.bitCount(s.lo);
for (long b = s.hi & grid.hi; b != 0; b &= b - 1) {
int offset = Long.bitCount(lo);
for (long b = hi & ghi; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
byte val = grid.g[64 | idx];
int i = offset + Long.bitCount(s.hi & ((1L << idx) - 1));
int i = offset + Long.bitCount(hi & ((1L << idx) - 1));
p |= ((long) (i * 26 + val)) << (i << 3);
}
} else {
int offset = Long.bitCount(s.hi);
for (long b = s.hi & grid.hi; b != 0; b &= b - 1) {
int offset = Long.bitCount(hi);
for (long b = hi & ghi; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
byte val = grid.g[64 | idx];
int i = Long.bitCount(s.hi & ~((1L << idx) | ((1L << idx) - 1)));
int i = Long.bitCount(hi & ~((1L << idx) | ((1L << idx) - 1)));
p |= ((long) (i * 26 + val)) << (i << 3);
}
for (long b = s.lo & grid.lo; b != 0; b &= b - 1) {
for (long b = lo & glo; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
byte val = grid.g[idx];
int i = offset + Long.bitCount(s.lo & ~((1L << idx) | ((1L << idx) - 1)));
int i = offset + Long.bitCount(lo & ~((1L << idx) | ((1L << idx) - 1)));
p |= ((long) (i * 26 + val)) << (i << 3);
}
}
@@ -775,51 +775,52 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
for (long b = s.hi; b != 0; b &= b - 1) cross += (count[64 | Long.numberOfTrailingZeros(b)] - 1);
return cross * 10 + s.length();
}
static boolean placeWord(Grid grid, Slot s, long w) {
if (s.increasing()) {
for (long b = s.lo & grid.lo; b != 0; b &= b - 1) {
static boolean placeWord(Grid grid, final int key, final long lo, final long hi, final long w) {
final long glo = grid.lo, ghi = grid.hi;
if (Slot.increasing(key)) {
for (long b = lo & glo; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
if (grid.g[idx] != Lemma.byteAt(w, Long.bitCount(s.lo & ((1L << idx) - 1)))) return false;
if (grid.g[idx] != Lemma.byteAt(w, Long.bitCount(lo & ((1L << idx) - 1)))) return false;
}
int bcLo = Long.bitCount(s.lo);
for (long b = s.hi & grid.hi; b != 0; b &= b - 1) {
int bcLo = Long.bitCount(lo);
for (long b = hi & ghi; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
if (grid.g[64 | idx] != Lemma.byteAt(w, bcLo + Long.bitCount(s.hi & ((1L << idx) - 1)))) return false;
if (grid.g[64 | idx] != Lemma.byteAt(w, bcLo + Long.bitCount(hi & ((1L << idx) - 1)))) return false;
}
long maskLo = s.lo & ~grid.lo, maskHi = s.hi & ~grid.hi;
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
if ((maskLo | maskHi) != 0) {
for (long b = maskLo; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
grid.g[idx] = Lemma.byteAt(w, Long.bitCount(s.lo & ((1L << idx) - 1)));
grid.g[idx] = Lemma.byteAt(w, Long.bitCount(lo & ((1L << idx) - 1)));
}
for (long b = maskHi; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
grid.g[64 | idx] = Lemma.byteAt(w, bcLo + Long.bitCount(s.hi & ((1L << idx) - 1)));
grid.g[64 | idx] = Lemma.byteAt(w, bcLo + Long.bitCount(hi & ((1L << idx) - 1)));
}
grid.lo |= maskLo;
grid.hi |= maskHi;
}
} else {
int bcHi = Long.bitCount(s.hi);
for (long b = s.hi & grid.hi; b != 0; b &= b - 1) {
int bcHi = Long.bitCount(hi);
for (long b = hi & ghi; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
if (grid.g[64 | idx] != Lemma.byteAt(w, Long.bitCount(s.hi & ~((1L << idx) | ((1L << idx) - 1))))) return false;
if (grid.g[64 | idx] != Lemma.byteAt(w, Long.bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))))) return false;
}
for (long b = s.lo & grid.lo; b != 0; b &= b - 1) {
for (long b = lo & glo; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
if (grid.g[idx] != Lemma.byteAt(w, bcHi + Long.bitCount(s.lo & ~((1L << idx) | ((1L << idx) - 1))))) return false;
if (grid.g[idx] != Lemma.byteAt(w, bcHi + Long.bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))))) return false;
}
long maskLo = s.lo & ~grid.lo, maskHi = s.hi & ~grid.hi;
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
if ((maskLo | maskHi) != 0) {
for (long b = maskHi; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
grid.g[64 | idx] = Lemma.byteAt(w, Long.bitCount(s.hi & ~((1L << idx) | ((1L << idx) - 1))));
grid.g[64 | idx] = Lemma.byteAt(w, Long.bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))));
}
for (long b = maskLo; b != 0; b &= b - 1) {
int idx = Long.numberOfTrailingZeros(b);
grid.g[idx] = Lemma.byteAt(w, bcHi + Long.bitCount(s.lo & ~((1L << idx) | ((1L << idx) - 1))));
grid.g[idx] = Lemma.byteAt(w, bcHi + Long.bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))));
}
grid.lo |= maskLo;
grid.hi |= maskHi;
@@ -946,7 +947,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
for (int i = 0, count, count2 = -1, bestScore = -1, n = TOTAL; i < n; i++) {
var s = slots[i];
if (assigned[s.key] != X) continue;
var pattern = patternForSlot(grid, s);
var pattern = patternForSlot(grid, s.key, s.lo, s.hi);
var index = dictIndex[s.length()];
count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index.posBitsets, index.numlong);
@@ -968,7 +969,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
current = PICK_DONE;
return;
}
var pattern = patternForSlot(grid, best);
var pattern = patternForSlot(grid, best.key, best.lo, best.hi);
var index = dictIndex[best.length()];
current = CARRIER;
current.slot = best;
@@ -1015,7 +1016,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
if (used.get(lemIdx)) continue;
val low = grid.lo;
val top = grid.hi;
if (!placeWord(grid, s, w)) continue;
if (!placeWord(grid, k, s.lo, s.hi, w)) continue;
used.set(lemIdx);
assigned[k] = w;
@@ -1024,7 +1025,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
assigned[k] = X;
used.clear(lemIdx);
//grid.undoPlace(undo[depth << 1], undo[(depth << 1) | 1]);
grid.lo = low;
grid.hi = top;
}
@@ -1043,7 +1043,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
if (used.get(lemIdx)) continue;
val low = grid.lo;
val top = grid.hi;
if (!placeWord(grid, s, w)) continue;
if (!placeWord(grid, k, s.lo, s.hi, w)) continue;
used.set(lemIdx);
assigned[k] = w;
@@ -1054,7 +1054,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
used.clear(lemIdx);
grid.lo = low;
grid.hi = top;
//grid.undoPlace(undo[depth << 1], undo[(depth << 1) | 1]);
}
backtracks++;