introduce bitloops
This commit is contained in:
@@ -203,13 +203,17 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
if ((ri & 64) == 0) {
|
||||
long mask = 1L << ri;
|
||||
lo |= mask;
|
||||
if ((idx & 1) != 0) vlo |= mask; else vlo &= ~mask;
|
||||
if ((idx & 2) != 0) rlo |= mask; else rlo &= ~mask;
|
||||
if ((idx & 1) != 0) vlo |= mask;
|
||||
else vlo &= ~mask;
|
||||
if ((idx & 2) != 0) rlo |= mask;
|
||||
else rlo &= ~mask;
|
||||
} else {
|
||||
long mask = 1L << (ri & 63);
|
||||
hi |= mask;
|
||||
if ((idx & 1) != 0) vhi |= mask; else vhi &= ~mask;
|
||||
if ((idx & 2) != 0) rhi |= mask; else rhi &= ~mask;
|
||||
if ((idx & 1) != 0) vhi |= mask;
|
||||
else vhi &= ~mask;
|
||||
if ((idx & 2) != 0) rhi |= mask;
|
||||
else rhi &= ~mask;
|
||||
}
|
||||
}
|
||||
public byte digitAt(int idx) {
|
||||
@@ -270,43 +274,22 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
}
|
||||
}
|
||||
|
||||
static class Grid {
|
||||
static record Grid(byte[] g, long lo, long hi) {
|
||||
|
||||
final byte[] g;
|
||||
long lo, hi;
|
||||
|
||||
public Grid(byte[] g) { this(g, 0, 0); }
|
||||
public Grid(byte[] g, long lo, long hi) {
|
||||
this.g = g;
|
||||
this.lo = lo;
|
||||
this.hi = hi;
|
||||
}
|
||||
static Grid createEmpty() { return new Grid(new byte[SIZE], X, X); }
|
||||
int digitAt(int index) { return g[index]; }
|
||||
public static int r(int offset) { return offset & 7; }
|
||||
public static int c(int offset) { return offset >>> 3; }
|
||||
static int offset(int r, int c) { return r | (c << 3); }
|
||||
Grid deepCopyGrid() { return new Grid(g.clone(), lo, hi); }
|
||||
public byte byteAt(int pos) { return g[pos]; }
|
||||
|
||||
void setClue(int idx, byte ch) {
|
||||
g[idx] = ch;
|
||||
if ((idx & 64) == 0) lo |= (1L << idx);
|
||||
else hi |= (1L << (idx & 63));
|
||||
}
|
||||
public Grid(byte[] g) { this(g, 0, 0); }
|
||||
static Grid createEmpty() { return new Grid(new byte[SIZE], X, X); }
|
||||
int digitAt(int index) { return g[index]; }
|
||||
public static int r(int offset) { return offset & 7; }
|
||||
public static int c(int offset) { return offset >>> 3; }
|
||||
static int offset(int r, int c) { return r | (c << 3); }
|
||||
public byte byteAt(int pos) { return g[pos]; }
|
||||
void setLetter(int idx, byte ch) { g[idx] = ch; }
|
||||
void clearletter(int idx) { g[idx] = DASH; }
|
||||
void clearClue(int idx) {
|
||||
g[idx] = DASH;
|
||||
if ((idx & 64) == 0) lo &= ~(1L << idx);
|
||||
else hi &= ~(1L << (idx & 63));
|
||||
}
|
||||
boolean isClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) != X : ((hi >>> (index & 63)) & 1L) != X; }
|
||||
boolean isClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) != X : ((hi >>> (index & 63)) & 1L) != X; }
|
||||
boolean notClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||
boolean notClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||
|
||||
int clueCount() { return Long.bitCount(lo) + Long.bitCount(hi); }
|
||||
boolean isClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) != X : ((hi >>> (index & 63)) & 1L) != X; }
|
||||
boolean isClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) != X : ((hi >>> (index & 63)) & 1L) != X; }
|
||||
boolean notClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||
boolean notClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||
int clueCount() { return Long.bitCount(lo) + Long.bitCount(hi); }
|
||||
|
||||
void forEachSlot(SlotVisitor visitor) {
|
||||
for (var l = lo; l != X; l &= l - 1) processSlot(this, visitor, Long.numberOfTrailingZeros(l));
|
||||
@@ -477,19 +460,19 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
|
||||
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;
|
||||
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 != 0) {
|
||||
rLo &= ((1L << Long.numberOfTrailingZeros(hLo)) - 1);
|
||||
@@ -606,7 +589,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
return penalty;
|
||||
}
|
||||
|
||||
SwedishGenerator.Clues randomMask() {
|
||||
Clues randomMask() {
|
||||
var g = Clues.createEmpty();
|
||||
for (int placed = 0, guard = 0, idx; placed < TARGET_CLUES && guard < 4000; guard++) {
|
||||
idx = rng.randint(0, SIZE_MIN_1);
|
||||
@@ -619,18 +602,18 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
}
|
||||
return g;
|
||||
}
|
||||
Clues mutate(Clues grid) {
|
||||
var g = grid.deepCopyGrid();
|
||||
Clues mutate(Clues clues) {
|
||||
var c = clues.deepCopyGrid();
|
||||
int ri;
|
||||
var bytes = MUTATE_RI[rng.randint(0, SIZE_MIN_1)];
|
||||
for (var k = 0; k < 4; k++) {
|
||||
ri = bytes[rng.randint(0, 624)];
|
||||
if (!g.clueless(ri)) {
|
||||
if (!c.clueless(ri)) {
|
||||
var d_idx = rng.randint2bitByte();
|
||||
if (g.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotDir(ri, d_idx)])) g.setClue(ri, d_idx);
|
||||
if (c.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotDir(ri, d_idx)])) c.setClue(ri, d_idx);
|
||||
}
|
||||
}
|
||||
return g;
|
||||
return c;
|
||||
}
|
||||
Clues crossover(Clues a, Clues other) {
|
||||
var out = a.deepCopyGrid();
|
||||
@@ -652,21 +635,21 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
|
||||
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));
|
||||
@@ -693,7 +676,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
return best;
|
||||
}
|
||||
|
||||
public SwedishGenerator.Grid generateMask(int popSize, int gens, int pairs) {
|
||||
public Clues generateMask(int popSize, int gens, int pairs) {
|
||||
class GridAndFit {
|
||||
|
||||
Clues grid;
|
||||
@@ -745,10 +728,10 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
var x = pop.get(i);
|
||||
if (x.fit() < best.fit()) best = x;
|
||||
}
|
||||
return best.grid.toGrid();
|
||||
return best.grid;
|
||||
}
|
||||
|
||||
static long patternForSlot(Grid grid, SwedishGenerator.Slot s) {
|
||||
static long patternForSlot(Grid grid, Slot s) {
|
||||
if ((s.lo & ~grid.lo) == 0 && (s.hi & ~grid.hi) == 0) return 0;
|
||||
long p = 0;
|
||||
if (s.increasing()) {
|
||||
@@ -855,7 +838,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int[] candidateInfoForPattern(long[] res, long pattern, SwedishGenerator.DictEntry entry, int lenb) {
|
||||
static int[] candidateInfoForPattern(long[] res, long pattern, DictEntry entry, int lenb) {
|
||||
int numLongs = entry.numlong;
|
||||
boolean first = true;
|
||||
|
||||
@@ -927,10 +910,10 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
for (int i = 0; i < slots.length; i++) slotScores[i] = slotScore(count, slots[i]);
|
||||
|
||||
}
|
||||
public static SwedishGenerator.FillResult fillMask(SwedishGenerator.Rng rng, Grid mask, DictEntry[] dictIndex) {
|
||||
public static FillResult fillMask(Rng rng, Grid mask, DictEntry[] dictIndex) {
|
||||
val multiThreaded = Thread.currentThread().getName().contains("pool");
|
||||
val NO_LOG = (!Main.VERBOSE || multiThreaded);
|
||||
val grid = mask.deepCopyGrid();
|
||||
val grid = mask;
|
||||
val used = new Bit1029();
|
||||
val assigned = new long[CLUE_INDEX_MAX_SIZE];
|
||||
val bitset = new long[2500];
|
||||
@@ -971,7 +954,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
System.out.print("\r" + Strings.padRight(msg, 120));
|
||||
System.out.flush();
|
||||
}
|
||||
SwedishGenerator.Pick chooseMRV() {
|
||||
Pick chooseMRV() {
|
||||
Slot best = null;
|
||||
for (int i = 0, count, count2 = -1, bestScore = -1, n = TOTAL; i < n; i++) {
|
||||
var s = slots[i];
|
||||
@@ -1079,7 +1062,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
var ok = solver.backtrack(0);
|
||||
// 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));
|
||||
var res = new FillResult(ok, new Gridded(grid), assigned, 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();
|
||||
|
||||
Reference in New Issue
Block a user