I am struggling with a lack of performance on the usage of a direct lookup table with equidistant inputs, for a 2D interpolation.
The goal is to find the 4 values (z00,z01,z11,z10) in the table z(x,y) corresponding to the two closest values of each of the inputs x and y, (x0 < x < x1) and (y0 < y < y1).
For example, the following lookup:
x
y | 1 | 2 | 3 |
---|---|---|---|
4 | 20 | 23 | 29 |
6 | 35 | 37 | 43 |
8 | 47 | 50 | 55 |
Is represented by the following array:
const f32 lookup {20,35,47,23,37,50,29,43,55}
Additionally together with the definition of the array a structure provides the following data to allow a more efficient lookup:
lowest_x = 1;
lowest_y = 4;
step_x = 1;
step_y = 2;
length_x = 3;
length_y = 3;
The most time consuming part of the algorithm is in finding the indices corresponding to the intersection of the values before and after the input x and y.
My current approach is to calculate them as follows:
Given that x0 and y0 are in indices multiple of:
index_x0 = u32 ((x-lowest_x)/step_x);
index_y0 = u32 ((y-lowest_y)/step_y);
Then x0,x1,y0 and y1 are:
x0 = lowest_x + index_x0 * step_x ;
x1 = x0 + step_x ;
y0 = lowest_y + index_y0 * step_y ;
y1 = y0 + step_y ;
And the 4 necessary values from the lookup z(x,y) are:
z00_index = index_x0*length_y0+index_y0;
z00= lookup[z00_index]
z01= lookup[z00_index+1]
z10= lookup[z00_index+length_y0];
z11= lookup[z00_index+length_y0+1];
The 2D interpolation is then performed as two interpolations of x along y0 and y1 and one interpolation of y:
zxy0 = (x1-x)/(x1-x0)*z00 + (x-x0)/(x1-x0)*z10;
zxy1 = (x1-x)/(x1-x0)*z01 + (x-x0)/(x1-x0)*z11;
z = (y1-y)/(y1-y0)*zxy0 + (y-y0)/(y-y0)*zxy1;
Any suggestions on how to improve this?