#ifndef WIDTH
#error "WIDTH is not defined"
#endif

#ifndef TYPE
#error "TYPE is not defined"
#endif

// Assume WIDTH contains the width of the grid
#define offset(x, y) (y * WIDTH  + x)

#define grid_get(grid, x, y) (grid[offset(x, y)])
#define grid_getp(grid, x, y) (grid + offset(x, y))

#define grid_xy(grid, x, y) (grid_get(grid, x, y))

#define grid_set(grid, x, y, v) (grid + offset(x, y) = v)
#define grid_setp(grid, x, y, v) (grid + offset(x, y) = v)

void search_max(
    global TYPE grid[],
    int radius,
    int x, int y,
    global int *rx, global int *ry
);

kernel void grid_search_max(
    global TYPE grid[],
    int radius,
    global int xPos[],
    global int yPos[],
    global int newXPos[],
    global int newYPos[]
){
    const int i = get_global_id(0);
    search_max(grid, radius, xPos[i], yPos[i], newXPos + i, newYPos + i);
}

void search_max(
    global TYPE grid[],
    int radius,
    int x, int y,
    global int *rx, global int *ry
){
    int i, j, r;
    int tmp_x = x, tmp_y = y;
    TYPE memo = grid_xy(grid, x, y);
    
    for (r = 1; r <= radius; r++) {
        
        j = y - r;
        for (i = x - r; i < x + r; i++) {
            if (i < 0 || i >= WIDTH || j < 0 || j >= HEIGHT) {
                continue;
            }
            
            TYPE value = grid_xy(grid, i, j);
            
            if (value > memo) {
                tmp_x = i;
                tmp_y = j;
                memo = value;
            }
        }

        i = x + r;
        for (j = y - r; j < y + r; j++) {
            if (i < 0 || i >= WIDTH || j < 0 || j >= HEIGHT) {
                continue;
            }
            
            TYPE value = grid_xy(grid, i, j);
             
            if (value > memo) {
                tmp_x = i;
                tmp_y = j;
                memo = value;
            }
        }

        j = y + r;
        for (i = x + r; i > x - r; i--) {
            if (i < 0 || i >= WIDTH || j < 0 || j >= HEIGHT) {
                continue;
            }
            
            TYPE value = grid_xy(grid, i, j);
             
            if (value > memo) {
                tmp_x = i;
                tmp_y = j;
                memo = value;
            }
        }

        i = x - r;
        for (j = y + r; j > y - r; j--) {
            if (i < 0 || i >= WIDTH || j < 0 || j >= HEIGHT) {
                continue;
            }
            
            TYPE value = grid_xy(grid, i, j);
             
            if (value > memo) {
                tmp_x = i;
                tmp_y = j;
                memo = value;
            }
        }
    }
    
    *rx = tmp_x;
    *ry = tmp_y;
    return;
}
