SL36FMAKKVKYSG4P2SQBPUKU5WRNUFYDLAPCZHO7DNFQZEKG4AIQC const min = @import("std").math.min;const max = @import("std").math.max;pub const HELPER = [_]u9{ 0o000, 0o000, 0o200, 0o201, 0o300, 0o301, 0o401, 0o400, 0o600, 0o601, 0o700, 0o701 };pub const INDEX = @import("utils").make_array([4]u9, index);fn index(pos: u6) [4]u9 {const a = @truncate(u3, pos);const b = @truncate(u3, pos >> 3);const c = switch (a) {3, 4 => a + @as(u4, if (b > 3) 7 else 5),else => switch (pos) {2, 10, 53, 61 => a,else => min(b, max(a, 7 - a)),},};return .{HELPER[a],HELPER[b],HELPER[c],0,};}
const pdep = @import("intrinsic.zig").pdep;const pext = @import("intrinsic.zig").pext;const MASK = @import("mask.zig").MASK;const INDEX = @import("index.zig").INDEX;const RESULT = @import("result.zig").RESULT;pub fn flip(board: [2]u64, place: u6) u64 {var ret: u64 = 0;comptime var i = 0;inline while (i < 3) : (i += 1)ret |= pdep(RESULT[@as(u64, INDEX[place][i]) * 32 + pext(board[0], MASK[place][i][0]) * 64 + pext(board[1], MASK[place][i][1])], MASK[place][i][1]);// plan to further shave 2KiB// ret |= pdep(RESULT[// @as(u64, INDEX[place][2]) * 32 | pext(board[0], MASK[place][i][0]) * 64 + pext(board[1], MASK[place][i][1])// ], MASK[place][i][1]);ret |= (((board[0] & MASK[place][3][0]) *% 0x05_0005) >> 9) & board[1] & MASK[place][3][1];return ret;}pub fn prefetch() void {@prefetch(&MASK, .{});@prefetch(&INDEX, .{});@prefetch(&RESULT, .{});}test {_ = @import("test.zig");_ = @import("index.zig");}
pub const MASK = @import("utils").make_array([4][2]u64, _mask);const mul = @import("utils").mul;const fill = @import("utils").fill;fn mask(pos: u6, comptime dir: u6) @Vector(2, u64) {const t = @as(u64, 1) << pos;const a = t | t << 8 | t >> 8;const b = a | (a << 1 & mul(0xFF, 0xFE)) | (a >> 1 & mul(0xFF, 0x7F));const r = fill(t, dir);return .{ r & ~b, r & ~t & switch (dir) {1 => mul(0xFF, 0x7E),8 => mul(0x7E, 0xFF),7, 9 => mul(0x7E, 0x7E),else => unreachable,} };}fn _mask(pos: u6) [4][2]u64 {// we don't support this case// zero for faster error findingif (@truncate(u1, mul(0x18, 0x18) >> pos) != 0) {return [_][2]u64{.{ 0, 0 }} ** 4;}const t: u64 = switch (pos) {2, 10, 53, 61 => 0,19, 20 => mul(0x07, 0xFF),43, 44 => mul(0xE0, 0xFF),else => switch (pos & 7) {2 => mul(0xFF, 0x07),5 => mul(0xFF, 0xE0),else => 0,},};const temp = mask(pos, 7) | mask(pos, 9);const tt = @splat(2, t);return .{ mask(pos, 1), mask(pos, 8), temp & ~tt, temp & tt };}
fn res(i: u3, p: u7, n: u7) u7 {const m = (@as(u7, 1) << i) - 1;return m & -%(@as(u7, 1) << (7 - @clz(~n & m)) & p) |((n >> i) + 1 & p >> i << 1) -| 1 << i;}const gen_mask = [4]u5{ 0b00101, 0b01010, 0b01010, 0b10100 };fn special(i: u2, p: u5, n: u5) u5 {const mask = gen_mask[i];if (i < 2) {return gen(mask, p, n, true) | gen(~mask, p, n, true);} else {return gen(mask, p, n, false) | gen(~mask, p, n, false);}}fn gen(mask: u5, p: u5, n: u5, is_up: bool) u5 {const nn = ~n & mask;const nnn = mask & ~if (is_up)-%(nn & -%nn)else@as(u6, 31) >> @clz(nn);if (nnn & p == 0) return 0;return @intCast(u5, nnn);}pub const RESULT = init: {@setEvalBranchQuota(1000000);var ret: [0x4000]u6 = undefined;for (@import("index.zig").HELPER) |i, index| {const range: u7 = switch (index) {0, 7 => 64,else => 32,};var j: u7 = 0;while (j < range) : (j += 1) {var k: u7 = 0;while (k < range) : (k += 1) {const ii = @as(u64, i + 2 * j) * 32 + k;if (index < 8) {const ind: u3 = @intCast(u3, index -| 1);ret[ii] = @intCast(u6, res(ind, j, k));} else {ret[ii] = special(@intCast(u2, index - 8), j, k);}}}}break :init ret;};