introduce bitloops

This commit is contained in:
mike
2026-01-12 11:46:38 +01:00
parent 6ef007522c
commit b6351a6fb2

View File

@@ -70,6 +70,8 @@ public record SwedishGenerator(Rng rng) {
static final int[][] MUTATE_RI = new int[SIZE][625]; static final int[][] MUTATE_RI = new int[SIZE][625];
static final long[] NBR8_PACKED_LO = Neighbors9x8.NBR8_PACKED_LO; static final long[] NBR8_PACKED_LO = Neighbors9x8.NBR8_PACKED_LO;
static final long[] NBR8_PACKED_HI = Neighbors9x8.NBR8_PACKED_HI; static final long[] NBR8_PACKED_HI = Neighbors9x8.NBR8_PACKED_HI;
static final long[] PATH_LO = Neighbors9x8.PATH_LO;
static final long[] PATH_HI = Neighbors9x8.PATH_HI;
static { static {
for (int i = 0; i < SIZE; i++) { for (int i = 0; i < SIZE; i++) {
@@ -305,10 +307,10 @@ public record SwedishGenerator(Rng rng) {
} }
} }
static record Slot(int key, long packedPos) { static record Slot(int key, long packedPos, long packedPoslo, long packedPoshi) {
static final int BIT_FOR_DIR = 3; static final int BIT_FOR_DIR = 3;
static Slot from(int key, long packedPos, int len) { return new Slot(key, packedPos | ((long) len << 56)); } static Slot from(int key, long packedPos, int len) { return new Slot(key, packedPos | ((long) len << 56), 0L, 0L); }
void undoPlace(Grid grid, int mask) { for (int i = 0, len = len(); i < len; i++) if ((mask & (1L << i)) != 0) grid.clearletter(pos(i)); } void undoPlace(Grid grid, int mask) { for (int i = 0, len = len(); i < len; i++) if ((mask & (1L << i)) != 0) grid.clearletter(pos(i)); }
public int len() { return (int) (packedPos >>> 56); } public int len() { return (int) (packedPos >>> 56); }
public int clueR() { return Grid.r((key >>> BIT_FOR_DIR)); } public int clueR() { return Grid.r((key >>> BIT_FOR_DIR)); }
@@ -322,6 +324,56 @@ public record SwedishGenerator(Rng rng) {
public static int packSlotDir(int idx, int d) { return (idx << BIT_FOR_DIR) | d; } public static int packSlotDir(int idx, int d) { return (idx << BIT_FOR_DIR) | d; }
} }
interface SlotVisitor2 {
void visitMasks(int slotDir, long loMask, long hiMask);
}
private static void processSlot(Grid grid, SlotVisitor2 visitor, int idx) {
int d = grid.digitAt(idx); // 1..4
int di = d - 1; // 0..3
int key = (idx << 2) | di;
long rayLo = PATH_LO[key];
long rayHi = PATH_HI[key];
// only consider clue cells
long hitsLo = rayLo & grid.lo;
long hitsHi = rayHi & grid.hi;
// slice ray to stop before first clue, depending on direction monotonicity
// right/down => increasing indices; up/left => decreasing indices
boolean increasing = (d == 2 || d == 3);
if (increasing) {
// first clue is lowest index among hits (lo first, then hi)
if (hitsLo != 0) {
long stop = 1L << Long.numberOfTrailingZeros(hitsLo);
rayLo &= (stop - 1);
rayHi = 0; // any hi is beyond the stop
} else if (hitsHi != 0) {
long stop = 1L << Long.numberOfTrailingZeros(hitsHi);
// keep all lo (lo indices are < any hi index), but cut hi below stop
rayHi &= (stop - 1);
}
} else {
// first clue is highest index among hits (hi first, then lo)
if (hitsHi != 0) {
int msb = 63 - Long.numberOfLeadingZeros(hitsHi);
long stop = 1L << msb;
rayHi &= ~((stop << 1) - 1); // keep bits > stop
rayLo = 0; // lo indices are below stop
} else if (hitsLo != 0) {
int msb = 63 - Long.numberOfLeadingZeros(hitsLo);
long stop = 1L << msb;
rayLo &= ~((stop << 1) - 1);
}
}
if ((rayLo | rayHi) != 0) {
visitor.visitMasks(Slot.packSlotDir(idx, d), rayLo, rayHi);
}
}
private static void processSlot(Grid grid, SlotVisitor visitor, int idx) { private static void processSlot(Grid grid, SlotVisitor visitor, int idx) {
var d = grid.digitAt(idx); var d = grid.digitAt(idx);
var packed = OFFSETS_D_IDX[(d - 1) | (idx << 2)]; var packed = OFFSETS_D_IDX[(d - 1) | (idx << 2)];
@@ -587,8 +639,6 @@ public record SwedishGenerator(Rng rng) {
var x = pop.get(i); var x = pop.get(i);
if (x.fit() < best.fit()) best = x; if (x.fit() < best.fit()) best = x;
} }
//pop.sort(Comparator.comparingLong(GridAndFit::fit));
//return pop.get(0).grid;
return best.grid; return best.grid;
} }