module env = import "../futhark_mpi/envelope" type envelope_1d_t [n] = env.envelope_1d_t [n] type envelope_2d_t [n][m][ty][tx] = env.envelope_2d_t [n][m][ty][tx] type~ envelope_1d_i8 = { west: []i8, -- 1 east: []i8 -- 0 } type~ envelope_2d_i8 = { north_west: [][]i8, -- 3 west: [][]i8, -- 7 south_west: [][]i8, -- 6 south: [][]i8, -- 4 south_east: [][]i8, -- 5 east: [][]i8, -- 0 north_east: [][]i8, -- 2 north: [][]i8 -- 1 } entry get_envelope_1d [n] (xs: [n]u8) (thickness: i64) : envelope_1d_t [thickness] = env.get_envelope_1d xs thickness entry get_envelope_2d [n][m] (matrix: [n][m]u8) (thickness_y: i64) (thickness_x: i64): envelope_2d_t [n][m][thickness_y][thickness_x] = env.get_envelope_2d matrix thickness_y thickness_x entry get_subdomain_1d = env.get_subdomain_1d entry get_subdomain_2d = env.get_subdomain_2d entry get_subdomain_3d = env.get_subdomain_3d let count_neighbours [n][m] (board: [n][m]i8) : [n][m]i8 = let north = rotate (-1) board let south = rotate 1 board let east = map(rotate 1) board let west = map(rotate (-1)) board let north_east = map(rotate 1) north let north_west = map(rotate (-1)) north let south_east = map(rotate 1) south let south_west = map(rotate (-1)) south in map3 (\(nwr,nr,ner) (wr, br, er) (swr, sr, ser) -> map3 (\(nw,n,ne) (w, _, e) (sw, s, se) -> nw + n + ne + w + e + sw + s + se) (zip3 nwr nr ner) (zip3 wr br er) (zip3 swr sr ser)) (zip3 north_west north north_east) (zip3 west board east) (zip3 south_west south south_east) let augment_board [n][m] (chunk_board:[n][m]i8) (envelope: envelope_2d_i8) :[][]i8 = tabulate_2d (n+2) (m+2) (\i j -> -- North-West if (i == 0 && j == 0) then envelope.north_west[0,0] -- North-East else if (i == 0 && j == m+1) then envelope.north_east[0,0] -- South-West else if (i == n+1 && j == 0) then envelope.south_west[0,0] -- South-East else if (i == n+1 && j == m+1) then envelope.south_east[0,0] -- North else if (i == 0) then envelope.north[0, j-1] -- West else if (j == 0) then envelope.west[i-1, 0] -- East else if (j == m + 1) then envelope.east[i-1, 0] -- South else if (i == n+1) then envelope.south[0,j-1] else chunk_board[i-1, j-1] ) -- (nw:[1][1]i8) (no:[1][m]i8) (ne:[1][1]i8) -- (we:[n][1]i8) (ea:[n][1]i8) -- (sw:[1][1]i8) (so:[1][m]i8) (se:[1][1]i8) entry next_chunk_board [n][m] (chunk_board :[n][m]i8) (envelope: envelope_2d_i8) :[n][m]i8 = let augmented_board = augment_board chunk_board envelope let neighbours = count_neighbours augmented_board let next_board = map2 (\augmented_board_r neighbours_r -> map2(\cell nb_alive_cells -> if (cell == 1 && (nb_alive_cells == 2 || nb_alive_cells == 3)) || (cell == 0 && nb_alive_cells == 3) then 1 else 0) augmented_board_r neighbours_r) augmented_board neighbours in next_board[1:n+1, 1:m+1] :> [n][m]i8