I have a linearized 2D array u
(block_height * block_width
) containing the values of a physical quantity over a regular 2D mesh. I need to downsample boundaries (top, bottom, left, right) of this array for communication with another process. I've refactored some code that does this, and I'd like people's thoughts on whether the new code is actually an improvement.
Old code:
if (dir == LEFT)
for(int j = 1; j <= block_height; j += 2)
left_edge[j/2] = (u[index(1,j)] + u[index(2,j)] +
u[index(1,j+1)] + u[index(2,j+1)]) / 4;
else if (dir == RIGHT)
for(int j = 1; j <= block_height; j += 2)
right_edge[j/2] = (u[index(block_width-1, j)] + u[index(block_width,j)] +
u[index(block_width-1, j+1)] + u[index(block_width, j+1)]) / 4;
else if (dir == UP)
for(int i = 1; i <= block_width; i += 2)
top_edge[i/2] = (u[index(i,1)] + u[index(i,2)] +
u[index(i+1,1)] + u[index(i+1,2)]) / 4;
else if (dir == DOWN)
for(int i = 1; i <= block_width; i += 2)
bottom_edge[i/2] = (u[index(i,block_height-1)] + u[index(i,block_height)] +
u[index(i+1,block_height-1)] + u[index(i+1,block_height)]) / 4;
New code:
double *boundary;
int k, fixed_dim;
int *x, *y;
switch (dir) {
case LEFT: case RIGHT: count = block_height; x = &fixed_dim; y = &k; break;
case UP: case DOWN: count = block_width; y = &fixed_dim; x = &k; break;
switch (dir) {
case LEFT: boundary = left_edge; fixed_dim = 1; break;
case RIGHT: boundary = right_edge; fixed_dim = block_width - 1; break;
case UP: boundary = top_edge; fixed_dim = 1; break;
case DOWN: boundary = bottom_edge; fixed_dim = block_height - 1; break;
}
for (k = 1; k <= count; k += 2)
boundary[k/2] = (u[index(*x, *y)] + u[index(*x+1, *y)] +
u[index(*x, *y+1)] + u[index(*x+1, *y+1)] )/ 4;
So, I've factored out the repeated for loop and made the logic more declarative, at the expense of introducing some additional indirection (including over which direction the loop iterates through memory!) and the variables to support it.
One obvious direction of future change for this code is increasing from 2 dimensions to 3 (and possible even more). I know which one I'd prefer to do that to, but if the old code is overwhelmingly clearer to people reading it, then the repetition may be worth retaining.