Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
**/.*
result
gate
compact/log.txt
compact/gate-compact
compact/cnw.c
compact/gate-compact.c
196 changes: 196 additions & 0 deletions compact/bottom.c
Original file line number Diff line number Diff line change
@@ -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 <unistd.h>

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");
}
52 changes: 52 additions & 0 deletions compact/compact.sh
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions compact/top.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

typedef uint64_t cell;

cell conway(cell in[9]) {