Skip to content
Snippets Groups Projects
gol.fut 3.87 KiB
Newer Older
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]
baptiste.coudray's avatar
baptiste.coudray committed
type~ side_envelope_3d_t = env.side_envelope_3d_t
type~ envelope_3d_t = env.envelope_3d_t

type~ envelope_1d_i8  = {
baptiste.coudray's avatar
baptiste.coudray committed
    east: []i8,    -- 0
    west: []i8     -- 1
}

type~ envelope_2d_i8  = {
baptiste.coudray's avatar
baptiste.coudray committed
    east: [][]i8,        -- 0
    north: [][]i8,       -- 1
    north_east: [][]i8,  -- 2
    north_west: [][]i8,  -- 3
    south: [][]i8,       -- 4
    south_east: [][]i8,  -- 5
baptiste.coudray's avatar
baptiste.coudray committed
    south_west: [][]i8,  -- 6
    west: [][]i8         -- 7
}

type~ side_envelope_3d_i32 = {
    east: [][][]i32,       -- edge
    north: [][][]i32,      -- edge
    north_east: [][][]i32, -- vertice
    north_west: [][][]i32, -- vertice
    south: [][][]i32,      -- edge
    south_east: [][][]i32, -- vertice
    south_west: [][][]i32, -- vertice
    surface: [][][]i32,
    west: [][][]i32        -- edge
}

type~ envelope_3d_i32 = {
    back: side_envelope_3d_t,   -- 0
    bottom: side_envelope_3d_t, -- 1
    front: side_envelope_3d_t,  -- 2
    left: side_envelope_3d_t,   -- 3
    right: side_envelope_3d_t,  -- 4
    top: side_envelope_3d_t     -- 5
}

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

baptiste.coudray's avatar
baptiste.coudray committed
entry get_envelope_3d [n][m][l] (cube: [n][m][l]u8) (thickness_y: i64) (thickness_x: i64) (thickness_z: i64): envelope_3d_t =
    env.get_envelope_3d cube thickness_y thickness_x thickness_z

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 =
baptiste.coudray's avatar
baptiste.coudray committed
    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]
            else if (i == 0 && j == m+1) then envelope.north_east[0,0]
            else if (i == n+1 && j == 0) then envelope.south_west[0,0]
            else if (i == n+1 && j == m+1) then envelope.south_east[0,0]
            else if (i == 0) then envelope.north[0, j-1]
            else if (j == 0) then envelope.west[i-1, 0]
            else if (j == m + 1) then envelope.east[i-1, 0]
            else if (i == n+1) then envelope.south[0,j-1]
            else chunk_board[i-1, j-1]
        )
baptiste.coudray's avatar
baptiste.coudray committed

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
baptiste.coudray's avatar
baptiste.coudray committed
    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