introduce bitloops
This commit is contained in:
@@ -179,63 +179,50 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
||||
long lo, hi, vlo, vhi, rlo, rhi;
|
||||
public static Clues createEmpty() { return new Clues(0, 0, 0, 0, 0, 0); }
|
||||
public Clues deepCopyGrid() { return new Clues(lo, hi, vlo, vhi, rlo, rhi); }
|
||||
boolean clueless(int idx) {
|
||||
if (!isClue(idx)) return false;
|
||||
if ((idx & 64) == 0) {
|
||||
clearClueLo(idx);
|
||||
} else {
|
||||
clearClueHi(idx);
|
||||
}
|
||||
boolean cluelessLo(int idx) {
|
||||
if (!isClueLo(idx)) return false;
|
||||
clearClueLo(~(1L << idx));
|
||||
return true;
|
||||
}
|
||||
boolean cluelessHi(int idx) {
|
||||
if (!isClueHi(idx)) return false;
|
||||
clearClueHi(~(1L << (idx & 63)));
|
||||
return true;
|
||||
}
|
||||
public boolean hasRoomForClue(long packed) { return (packed) != X && notClue(packed & 0x7FL) && notClue((packed >>> 7) & 0x7FL); }
|
||||
|
||||
public void setClue(int ri, byte idx) {
|
||||
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;
|
||||
} 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;
|
||||
}
|
||||
public void setClueLo(long mask, byte idx) {
|
||||
lo |= mask;
|
||||
if ((idx & 1) != 0) vlo |= mask;
|
||||
else vlo &= ~mask;
|
||||
if ((idx & 2) != 0) rlo |= mask;
|
||||
else rlo &= ~mask;
|
||||
}
|
||||
public void setClueHi(long mask, byte idx) {
|
||||
hi |= mask;
|
||||
if ((idx & 1) != 0) vhi |= mask;
|
||||
else vhi &= ~mask;
|
||||
if ((idx & 2) != 0) rhi |= mask;
|
||||
else rhi &= ~mask;
|
||||
}
|
||||
public byte digitAtRevLo(int idx) { return (byte) (2 | ((vlo >>> idx) & 1L)); }
|
||||
public byte digitAtRevHi(int idx) { return (byte) (2 | ((vhi >>> (idx & 63)) & 1L)); }
|
||||
public byte digitAtDevLo(int idx) { return (byte) ((vlo >>> idx) & 1L); }
|
||||
public byte digitAtDevHi(int idx) { return (byte) ((vhi >>> (idx & 63)) & 1L); }
|
||||
public byte digitAt(int idx) {
|
||||
if ((idx & 64) == 0) {
|
||||
int v = (int) ((vlo >>> idx) & 1L);
|
||||
int r = (int) ((rlo >>> idx) & 1L);
|
||||
return (byte) ((r << 1) | v);
|
||||
} else {
|
||||
int v = (int) ((vhi >>> (idx & 63)) & 1L);
|
||||
int r = (int) ((rhi >>> (idx & 63)) & 1L);
|
||||
return (byte) ((r << 1) | v);
|
||||
}
|
||||
}
|
||||
public void clearClueLo(int idx) {
|
||||
long mask = ~(1L << idx);
|
||||
public int digitAtHi(int idx) { return (int) ((((rhi >>> idx) & 1L) << 1) | ((vhi >>> idx) & 1L)); }
|
||||
public int digitAtLo(int idx) { return (int) ((((rlo >>> idx) & 1L) << 1) | ((vlo >>> idx) & 1L)); }
|
||||
public void clearClueLo(long mask) {
|
||||
lo &= mask;
|
||||
vlo &= mask;
|
||||
rlo &= mask;
|
||||
}
|
||||
public void clearClueHi(int idx) {
|
||||
long mask = ~(1L << (idx & 63));
|
||||
public void clearClueHi(long mask) {
|
||||
hi &= mask;
|
||||
vhi &= mask;
|
||||
rhi &= mask;
|
||||
}
|
||||
public boolean isClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) != X : ((hi >>> (index & 63)) & 1L) != X; }
|
||||
public boolean isClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) != X : ((hi >>> (index & 63)) & 1L) != X; }
|
||||
public boolean isClueLo(int index) { return ((lo >>> index) & 1L) != X; }
|
||||
public boolean isClueHi(int index) { return ((hi >>> (index & 63)) & 1L) != X; }
|
||||
public boolean notClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||
public boolean notClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||
|
||||
@@ -501,18 +488,18 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
||||
long seenLo = X, seenHi = X;
|
||||
|
||||
// loop over beide helften
|
||||
for (int base = 0; base <= 64; base += 64) {
|
||||
for (int base = 0, size, sp, cur; base <= 64; base += 64) {
|
||||
long clueMask = (base == 0) ? lo_cl : hi_cl;
|
||||
long seenMask = (base == 0) ? seenLo : seenHi;
|
||||
|
||||
// "unseen clues" in deze helft
|
||||
for (long bits = clueMask & ~seenMask; bits != X; bits &= bits - 1) {
|
||||
for (long bits = clueMask & ~seenMask, nLo, nHi; bits != X; bits &= bits - 1) {
|
||||
int clueIdx = base | Long.numberOfTrailingZeros(bits);
|
||||
|
||||
// start nieuwe component
|
||||
int size = 0;
|
||||
int sp = 0;
|
||||
stack[sp++] = clueIdx;
|
||||
size = 0;
|
||||
stack[0] = clueIdx;
|
||||
sp = 1;
|
||||
|
||||
// mark seen
|
||||
if ((clueIdx & 64) == 0) seenLo |= 1L << clueIdx;
|
||||
@@ -520,12 +507,12 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
||||
|
||||
// flood fill / bfs
|
||||
while (sp > 0) {
|
||||
int cur = stack[--sp];
|
||||
cur = stack[--sp];
|
||||
size++;
|
||||
|
||||
// neighbors als 2x long masks
|
||||
long nLo = NBR8_PACKED_LO[cur];
|
||||
long nHi = NBR8_PACKED_HI[cur];
|
||||
nLo = NBR8_PACKED_LO[cur];
|
||||
nHi = NBR8_PACKED_HI[cur];
|
||||
|
||||
// filter: alleen clues, en nog niet seen
|
||||
nLo &= lo_cl & ~seenLo;
|
||||
@@ -584,32 +571,51 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
||||
|
||||
Clues randomMask(final int clueSize) {
|
||||
var g = Clues.createEmpty();
|
||||
for (int placed = 0, guard = 0, idx; placed < clueSize && guard < 4000; guard++) {
|
||||
for (int placed = 0, guard = 0, ri; placed < clueSize && guard < 4000; guard++) {
|
||||
|
||||
idx = rng.randint0_SIZE();
|
||||
if (g.isClue(idx)) continue;
|
||||
var d_idx = rng.randint2bitByte();
|
||||
if (g.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, d_idx)])) {
|
||||
g.setClue(idx, d_idx);
|
||||
placed++;
|
||||
ri = rng.randint0_SIZE();
|
||||
if (isLo(ri)) {
|
||||
if (g.isClueLo(ri)) continue;
|
||||
var d_idx = rng.randint2bitByte();
|
||||
if (g.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(ri, d_idx)])) {
|
||||
g.setClueLo(1L << ri, d_idx);
|
||||
placed++;
|
||||
}
|
||||
} else {
|
||||
if (g.isClueHi(ri)) continue;
|
||||
var d_idx = rng.randint2bitByte();
|
||||
if (g.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(ri, d_idx)])) {
|
||||
g.setClueHi(1L << (ri & 63), d_idx);
|
||||
placed++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return g;
|
||||
}
|
||||
Clues mutate(Clues c) {
|
||||
static boolean isLo(int n) { return (n & 64) == 0; }
|
||||
Clues mutate(SwedishGenerator.Clues c) {
|
||||
int ri;
|
||||
var bytes = MUTATE_RI[rng.randint0_SIZE()];
|
||||
for (var k = 0; k < 4; k++) {
|
||||
ri = bytes[rng.randint0_624()];
|
||||
if (!c.clueless(ri)) {
|
||||
var d_idx = rng.randint2bitByte();
|
||||
if (c.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(ri, d_idx)])) c.setClue(ri, d_idx);
|
||||
if (isLo(ri)) {
|
||||
if (!c.cluelessLo(ri)) {
|
||||
var d_idx = rng.randint2bitByte();
|
||||
if (c.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(ri, d_idx)])) c.setClueLo(1L << ri, d_idx);
|
||||
}
|
||||
} else {
|
||||
if (!c.cluelessHi(ri)) {
|
||||
var d_idx = rng.randint2bitByte();
|
||||
if (c.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(ri, d_idx)])) c.setClueHi(1L << (ri & 63), d_idx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return c;
|
||||
}
|
||||
Clues crossover(Clues a, Clues other) {
|
||||
var out = a.deepCopyGrid();
|
||||
|
||||
var theta = rng.nextFloat() * Math.PI;
|
||||
var nc = Math.cos(theta);
|
||||
var nr = Math.sin(theta);
|
||||
@@ -622,20 +628,20 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
||||
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);
|
||||
var out = new Clues(
|
||||
(a.lo & ~maskLo) | (other.lo & maskLo),
|
||||
(a.hi & ~maskHi) | (other.hi & maskHi),
|
||||
(a.vlo & ~maskLo) | (other.vlo & maskLo),
|
||||
(a.vhi & ~maskHi) | (other.vhi & maskHi),
|
||||
(a.rlo & ~maskLo) | (other.rlo & maskLo),
|
||||
(a.rhi & ~maskHi) | (other.rhi & maskHi));
|
||||
|
||||
for (var lo = out.lo; lo != X; lo &= lo - 1L) clearCluesLo(out, Long.numberOfTrailingZeros(lo));
|
||||
for (var hi = out.hi; hi != X; hi &= hi - 1L) clearCluesHi(out, 64 | Long.numberOfTrailingZeros(hi));
|
||||
for (var hi = out.hi; hi != X; hi &= hi - 1L) clearCluesHi(out, Long.numberOfTrailingZeros(hi));
|
||||
return out;
|
||||
}
|
||||
public static void clearCluesLo(Clues out, int idx) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, out.digitAt(idx))])) out.clearClueLo(idx); }
|
||||
public static void clearCluesHi(Clues out, int idx) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, out.digitAt(idx))])) out.clearClueHi(idx); }
|
||||
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 clearCluesHi(Clues out, int idx) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(64 | idx, out.digitAtHi(idx))])) out.clearClueHi(~(1L << idx)); }
|
||||
|
||||
Clues hillclimb(Clues start, int clue_size, int limit) {
|
||||
var best = start;
|
||||
@@ -723,26 +729,26 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
||||
long p = 0;
|
||||
if (Slot.increasing(key)) {
|
||||
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||
int idx = Long.numberOfTrailingZeros(b);
|
||||
int i = Long.bitCount(lo & ((1L << idx) - 1));
|
||||
int idx = Long.numberOfTrailingZeros(b);
|
||||
int i = Long.bitCount(lo & ((1L << idx) - 1));
|
||||
p |= ((long) (i * 26 + g[idx])) << (i << 3);
|
||||
}
|
||||
int offset = Long.bitCount(lo);
|
||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||
int idx = Long.numberOfTrailingZeros(b);
|
||||
int i = offset + Long.bitCount(hi & ((1L << idx) - 1));
|
||||
int idx = Long.numberOfTrailingZeros(b);
|
||||
int i = offset + Long.bitCount(hi & ((1L << idx) - 1));
|
||||
p |= ((long) (i * 26 + g[64 | idx])) << (i << 3);
|
||||
}
|
||||
} else {
|
||||
int offset = Long.bitCount(hi);
|
||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||
int idx = Long.numberOfTrailingZeros(b);
|
||||
int i = Long.bitCount(hi & ~((1L << idx) | ((1L << idx) - 1)));
|
||||
int idx = Long.numberOfTrailingZeros(b);
|
||||
int i = Long.bitCount(hi & ~((1L << idx) | ((1L << idx) - 1)));
|
||||
p |= ((long) (i * 26 + g[64 | idx])) << (i << 3);
|
||||
}
|
||||
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||
int idx = Long.numberOfTrailingZeros(b);
|
||||
int i = offset + Long.bitCount(lo & ~((1L << idx) | ((1L << idx) - 1)));
|
||||
int idx = Long.numberOfTrailingZeros(b);
|
||||
int i = offset + Long.bitCount(lo & ~((1L << idx) | ((1L << idx) - 1)));
|
||||
p |= ((long) (i * 26 + g[idx])) << (i << 3);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user