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; if ((idx & 2) != 0) rhi |= mask;
else rhi &= ~mask; else rhi &= ~mask;
} }
int digitAtLo(int idx) { return (int) ((((rlo >>> idx) & 1L) << 1) | ((vlo >>> idx) & 1L)); }
void clearClueLo(long mask) { void clearClueLo(long mask) {
lo &= mask; lo &= mask;
vlo &= 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; return (Long.bitCount(matchLo & MASK_LO) + Long.bitCount(matchHi & MASK_HI)) / SIZED;
} }
public Grid toGrid() { return new Grid(new byte[SIZE], lo, hi); } 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), 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) 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)); 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 String[] clue(long w) { return CsvIndexService.clues(unpackIndex(w)); }
static int simpel(long w) { return CsvIndexService.simpel(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 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) { public static String asWord(long word) {
val len = Lemma.length(word); val len = Lemma.length(word);
var b = BYTES.get();//new byte[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); 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 rayLo = PATH_LO[key];
long rayHi = PATH_HI[key]; long rayHi = PATH_HI[key];
long hitsLo = rayLo & c.lo; long hitsLo = rayLo & c.lo;
@@ -589,10 +588,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
return g; return g;
} }
static boolean isLo(int n) { return (n & 64) == 0; } static boolean isLo(int n) { return (n & 64) == 0; }
Clues mutate(SwedishGenerator.Clues c) { Clues mutate(Clues c) {
int ri;
var bytes = MUTATE_RI[rng.randint0_SIZE()]; 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()]; ri = bytes[rng.randint0_624()];
if (isLo(ri)) { if (isLo(ri)) {
if (!c.cluelessLo(ri)) { if (!c.cluelessLo(ri)) {
@@ -631,9 +629,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
(a.rlo & ~maskLo) | (other.rlo & maskLo), (a.rlo & ~maskLo) | (other.rlo & maskLo),
(a.rhi & ~maskHi) | (other.rhi & maskHi)); (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), 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), 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), 2);
@@ -644,7 +639,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (Long.numberOfTrailingZeros(h)), 3); for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (Long.numberOfTrailingZeros(h)), 3);
return c; 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 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 clearCluesHi(Clues out, int idx, int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(64 | idx, d)])) out.clearClueHi(~(1L << idx)); }
@@ -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 multiThreaded = Thread.currentThread().getName().contains("pool");
val NO_LOG = (!Main.VERBOSE || multiThreaded); val NO_LOG = (!Main.VERBOSE || multiThreaded);
val grid = mask; val grid = mask;
@@ -909,7 +903,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
class Solver { class Solver {
private final SwedishGenerator.Pick CARRIER = new Pick(null, null, 0); private final Pick CARRIER = new Pick(null, null, 0);
long nodes; long nodes;
long backtracks; long backtracks;
int lastMRV; int lastMRV;
@@ -1064,7 +1058,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
// final progress line // final progress line
var res = new FillResult(ok, new Gridded(grid), assigned, 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) { if (!multiThreaded) {
System.out.print("\r" + Strings.padRight("", 120) + "\r"); System.out.print("\r" + Strings.padRight("", 120) + "\r");
System.out.flush(); System.out.flush();