diff --git a/.gitignore b/.gitignore index 204888b..1491482 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ **/.* result gate +compact/log.txt +compact/gate-compact +compact/cnw.c +compact/gate-compact.c diff --git a/compact/bottom.c b/compact/bottom.c new file mode 100644 index 0000000..b00eab7 --- /dev/null +++ b/compact/bottom.c @@ -0,0 +1,196 @@ + return out; +} + +// human attempt, 54 gates +cell conway_clayton(cell in[9]) { + // pairs + cell p00 = ~(in[0] | in[1]); + cell p10 = ~(in[2] | in[3]); + cell p20 = ~(in[5] | in[6]); + cell p30 = ~(in[7] | in[8]); + cell p01 = in[0] ^ in[1]; + cell p11 = in[2] ^ in[3]; + cell p21 = in[5] ^ in[6]; + cell p31 = in[7] ^ in[8]; + cell p02 = in[0] & in[1]; + cell p12 = in[2] & in[3]; + cell p22 = in[5] & in[6]; + cell p32 = in[7] & in[8]; + // halfs + cell h00 = p00 & p10; + cell h10 = p20 & p30; + cell h01 = (p00 & p11) | (p10 & p01); + cell h11 = (p20 & p31) | (p30 & p21); + cell h03 = (p02 & p11) | (p12 & p01); + cell h13 = (p22 & p31) | (p32 & p21); + cell h02 = (p02 & p10) | (p00 & p12) | (p01 & p11); + cell h12 = (p22 & p30) | (p20 & p32) | (p21 & p31); + // neighbors + cell n2 = (h01 & h11) | (h02 & h10) | (h00 & h12); + cell n3 = (h03 & h10) | (h13 & h00) | (h02 & h11 ) | (h12 & h01); + // rule + cell out = n3 | (in[4] & n2); + return out; +} + +typedef struct { + cell* cells; + size_t cells_len; + size_t width; + size_t height; +} board_t; + +void fatal(const char* message) { + fprintf(stderr, "fatal: %s\n", message); + exit(1); +} + +board_t board_new(size_t width, size_t height) { + if (width % 64 != 0) { fatal("board width must be multiple of 64"); } + + size_t cells_len = (size_t)(width / 64) * height; + cell* cells = malloc(cells_len * sizeof(cell)); + if (cells == NULL) { fatal("not able to allocate memory for board "); } + + board_t board = { cells, cells_len, width, height }; + return board; +} + +// https://en.wikipedia.org/wiki/Xorshift +// constant is frac(golden_ratio) * 2^64 +// global state bad cry me a river +uint64_t rand_state = 0x9e3779b97f4a7c55; + +uint64_t rand_uint64_t() { + uint64_t x = rand_state; + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + rand_state = x; + return x; +} + +cell rand_cell() { + // return 0x0101010101010101; + return rand_uint64_t(); +} + +void rand_board_mut(board_t *board) { + for (size_t i = 0; i < board->cells_len; ++i) { + board->cells[i] = rand_cell(); + } +} + +void board_debug(board_t *board) { + size_t cells_per_row = board->width / 64; + for (size_t i = 0; i < board->height; ++i) { + for (size_t j = 0; j < cells_per_row; ++j) { + cell current_cell = board->cells[i * cells_per_row + j]; + for (int k = 0; k < 64; k++) { + if ((current_cell >> k) & 1) { + printf("█ "); + } else { + printf(" "); + } + } + } + printf("|\n"); + } + for (size_t i = 0; i < board->width * 2; ++i) { + printf("-"); + } + printf("\n"); +} + +void board_step_scratch_mut( + board_t *board, + board_t *scratch_left, + board_t *scratch_right +) { + size_t cells_per_row = board->width / 64; + for (size_t i = 0; i < board->height; ++i) { + cell msb_prev = (board->cells[i * cells_per_row + cells_per_row - 1] >> 63) & 1; + for (size_t j = 0; j < cells_per_row; ++j) { + size_t idx = i * cells_per_row + j; + cell cell_curr = board->cells[idx]; + cell cell_shift = cell_curr << 1; + cell msb_curr = (cell_curr >> 63) & 1; + scratch_left->cells[idx] = cell_shift | msb_prev; + msb_prev = msb_curr; + } + } + for (size_t i = 0; i < board->height; ++i) { + cell lsb_next = board->cells[i * cells_per_row] & 1; + for (size_t j = cells_per_row; j-- > 0; ) { + size_t idx = i * cells_per_row + j; + cell cell_curr = board->cells[idx]; + cell cell_shift = cell_curr >> 1; + cell lsb_curr = cell_curr & 1; + scratch_right->cells[idx] = cell_shift | (lsb_next << 63); + lsb_next = lsb_curr; + } + } +} + +void board_step_mut( + board_t *board, + board_t *s_left, // scratch + board_t *s_right, + board_t *s_out +) { + board_step_scratch_mut(board, s_left, s_right); + + size_t step = board->width / 64; + size_t wrap = board->cells_len; + + for (size_t i = 0; i < board->cells_len; i++) { + cell in[9]; + size_t i_top = (i + wrap - step) % wrap; + size_t i_bottom = (i + step) % wrap; + // top row + in[0] = s_left->cells[i_top]; + in[1] = board->cells[i_top]; + in[2] = s_right->cells[i_top]; + // middle row + in[3] = s_left->cells[i]; + in[4] = board->cells[i]; + in[5] = s_right->cells[i]; + // bottom row + in[6] = s_left->cells[i_bottom]; + in[7] = board->cells[i_bottom]; + in[8] = s_right->cells[i_bottom]; + // update output + s_out->cells[i] = conway(in); + } + + // double-buffering + cell* tmp_cells = board->cells; + board->cells = s_out->cells; + s_out->cells = tmp_cells; +} + +#include + +int main() { + size_t width = 512; + size_t height = 512; + + board_t board = board_new(width, height); + board_t sl = board_new(width, height); + board_t sr = board_new(width, height); + board_t so = board_new(width, height); + + rand_board_mut(&board); + + for (size_t count = 0; count < 100000; count++) { + // vvv comment out for benchmarking + printf("\033[H"); + board_debug(&board); + printf("Step: %zu\n", count); + sleep(1); + // ^^^ comment out for benchmarking + board_step_mut(&board, &sl, &sr, &so); + } + + printf("done!\n"); +} diff --git a/compact/compact.sh b/compact/compact.sh new file mode 100755 index 0000000..e934bf7 --- /dev/null +++ b/compact/compact.sh @@ -0,0 +1,52 @@ +# cut out just the generated portion (simple enough, no need to modify python part) +cat ../gate.c | head -n 190 | tail -n 183 > cnw.c + +defs= + +rm log.txt -f; + +for vr in $(awk -F' ' '{ print $2 }' cnw.c); do + + printf -- "\n--> $vr <--\n" >> log.txt + + # find all variables that only get used once + grep -n -E "[ (]~?$vr[ ;)]" cnw.c > tmp.grep; + if [ $(wc -l tmp.grep | sed "s/ [^ ]*$//") -eq 2 ]; then + +echo "tmp.grep: $(cat tmp.grep)" >> log.txt + + # find the definition of the variable + def=$(sed -n "1s/:.*\$//p" tmp.grep) + + defs="$defs\n${def}d" + +echo "def=$def" >> log.txt + + # find the only use of the variable + use=$(sed -n "2s/:.*\$//p" tmp.grep) + +echo "use=$use" >> log.txt + + # find just the definition's rvalue + def2=$(sed -n "${def}p" cnw.c | sed -E "s/ *cell [^ ]+ = //" | sed -E "s/;//" | sed "s/&/\\\&/g") + +echo "def2=$def2" >> log.txt + + # replace the single occurence with def2 + sed -i -E "${use}s/([ (]~?)$vr([ ;)])/\1($def2)\2/" cnw.c + + fi + + rm tmp.grep + +done + +sed -i "$(echo -e $defs)" cnw.c + +# combine together, because I don't know how to use the template +cat top.c cnw.c bottom.c > gate-compact.c + +CC="${CC:-gcc}" + +# compile using gcc or your compiler +$CC gate-compact.c -o gate-compact diff --git a/compact/top.c b/compact/top.c new file mode 100644 index 0000000..ba4271a --- /dev/null +++ b/compact/top.c @@ -0,0 +1,9 @@ +#include +#include +#include + +typedef uint64_t cell; + +cell conway(cell in[9]) { + +