introduce bitloops

This commit is contained in:
mike
2026-01-16 23:48:36 +01:00
parent aceaa0fc18
commit 60b7509bf6

View File

@@ -205,7 +205,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
if ((idx & 2) != 0) rhi |= mask;
else rhi &= ~mask;
}
int digitAtLo(int idx) { return (int) ((((rlo >>> idx) & 1L) << 1) | ((vlo >>> idx) & 1L)); }
void clearClueLo(long mask) {
lo &= mask;
vlo &= mask;
@@ -229,7 +228,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
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(SwedishGenerator.SlotVisitor visitor) {
public void forEachSlot(SlotVisitor visitor) {
for (var l = lo & ~rlo & vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(Long.numberOfTrailingZeros(l), 1));
for (var l = lo & ~rlo & ~vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(Long.numberOfTrailingZeros(l), 0));
for (var l = lo & rlo & ~vlo; l != X; l &= l - 1) processSlotRev(this, visitor, Slot.packSlotKey(Long.numberOfTrailingZeros(l), 2));
@@ -277,7 +276,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
static String[] clue(long w) { return CsvIndexService.clues(unpackIndex(w)); }
static int simpel(long w) { return CsvIndexService.simpel(unpackIndex(w)); }
static int length(long word) { return ((63 - Long.numberOfLeadingZeros(word & LETTER_MASK)) / 5) + 1; }
static ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[SwedishGenerator.MAX_WORD_LENGTH]);
static ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[MAX_WORD_LENGTH]);
public static String asWord(long word) {
val len = Lemma.length(word);
var b = BYTES.get();//new byte[Lemma.length(word)];
@@ -370,7 +369,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
visitor.visit(key, rayLo, rayHi);
}
private static void processSlot(Clues c, SwedishGenerator.SlotVisitor visitor, int key) {
private static void processSlot(Clues c, SlotVisitor visitor, int key) {
long rayLo = PATH_LO[key];
long rayHi = PATH_HI[key];
long hitsLo = rayLo & c.lo;
@@ -589,10 +588,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
return g;
}
static boolean isLo(int n) { return (n & 64) == 0; }
Clues mutate(SwedishGenerator.Clues c) {
int ri;
Clues mutate(Clues c) {
var bytes = MUTATE_RI[rng.randint0_SIZE()];
for (var k = 0; k < 4; k++) {
for (int k = 0, ri; k < 4; k++) {
ri = bytes[rng.randint0_624()];
if (isLo(ri)) {
if (!c.cluelessLo(ri)) {
@@ -631,22 +629,18 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
(a.rlo & ~maskLo) | (other.rlo & maskLo),
(a.rhi & ~maskHi) | (other.rhi & maskHi));
// for (var lo = c.lo; lo != X; lo &= lo - 1L) clearCluesLo(c, Long.numberOfTrailingZeros(lo));
// for (var hi = c.hi; hi != X; hi &= hi - 1L) clearCluesHi(c, Long.numberOfTrailingZeros(hi));
for (var l = c.lo & ~c.rlo & ~c.vlo ; l != X; l &= l - 1) clearCluesLo(c,Long.numberOfTrailingZeros(l), 0);
for (var l = c.lo & ~c.rlo & c.vlo ; l != X; l &= l - 1) clearCluesLo(c,Long.numberOfTrailingZeros(l), 1);
for (var l = c.lo & c.rlo & ~c.vlo ; l != X; l &= l - 1) clearCluesLo(c,Long.numberOfTrailingZeros(l), 2);
for (var l = c.lo & c.rlo & c.vlo ; l != X; l &= l - 1) clearCluesLo(c,Long.numberOfTrailingZeros(l), 3);
for (var h = c.hi & ~c.rhi & ~c.vhi ; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 0);
for (var h = c.hi & ~c.rhi & c.vhi ; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 1);
for (var h = c.hi & c.rhi & ~c.vhi ; h != X; h &= h - 1) clearCluesHi(c,( Long.numberOfTrailingZeros(h)), 2);
for (var h = c.hi & c.rhi & ~c.vhi ; h != X; h &= h - 1) clearCluesHi(c,( Long.numberOfTrailingZeros(h)), 3);
for (var l = c.lo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 0);
for (var l = c.lo & ~c.rlo & c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 1);
for (var l = c.lo & c.rlo & ~c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 2);
for (var l = c.lo & c.rlo & c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 3);
for (var h = c.hi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 0);
for (var h = c.hi & ~c.rhi & c.vhi; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 1);
for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (Long.numberOfTrailingZeros(h)), 2);
for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (Long.numberOfTrailingZeros(h)), 3);
return c;
}
public static void clearCluesLo(Clues out, int idx) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, out.digitAtLo(idx))])) out.clearClueLo(~(1L << idx)); }
public static void clearCluesLo(Clues out, int idx,int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, d)])) out.clearClueLo(~(1L << idx)); }
public static void clearCluesHi(Clues out, int idx,int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(64 | idx, d)])) out.clearClueHi(~(1L << idx)); }
public static void clearCluesLo(Clues out, int idx, int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, d)])) out.clearClueLo(~(1L << idx)); }
public static void clearCluesHi(Clues out, int idx, int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(64 | idx, d)])) out.clearClueHi(~(1L << idx)); }
Clues hillclimb(Clues start, int clue_size, int limit) {
var best = start;
@@ -891,7 +885,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
}
}
public static SwedishGenerator.FillResult fillMask(Rng rng, Slot[] slots, Grid mask) {
public static FillResult fillMask(Rng rng, Slot[] slots, Grid mask) {
val multiThreaded = Thread.currentThread().getName().contains("pool");
val NO_LOG = (!Main.VERBOSE || multiThreaded);
val grid = mask;
@@ -909,7 +903,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
class Solver {
private final SwedishGenerator.Pick CARRIER = new Pick(null, null, 0);
private final Pick CARRIER = new Pick(null, null, 0);
long nodes;
long backtracks;
int lastMRV;
@@ -1064,7 +1058,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
// final progress line
var res = new FillResult(ok, new Gridded(grid), assigned,
new SwedishGenerator.FillStats(solver.nodes, solver.backtracks, (System.currentTimeMillis() - t0) / 1000.0, solver.lastMRV));
new FillStats(solver.nodes, solver.backtracks, (System.currentTimeMillis() - t0) / 1000.0, solver.lastMRV));
if (!multiThreaded) {
System.out.print("\r" + Strings.padRight("", 120) + "\r");
System.out.flush();