LUT_2D#

Description#

The uz_LUT_2D module provides a 2D look-up table with binary search, bilinear interpolation and value clamping. It uses the uz_array_float_t type from Array for both breakpoint vectors and flattened data storage. The breakpoint arrays for x-axis and y-axis must both be strictly increasing (no duplicates) and contain at least two entries. The flattened data array must be in row-major order (x-index changes fastest), and must have breakpoints_x.length * breakpoints_y.length entries.

Data indexing of the flattened array follows:

\[i = y_{idx} \cdot N_x + x_{idx}\]

where \(N_x\) is the number of x-axis breakpoints.

For the code example below with LUT_breakpoints_x_array = {0, 1, 2}, LUT_breakpoints_y_array = {0, 1, 2}, and LUT_data_array = {0, 1, 2, 10, 11, 12, 20, 21, 22}, the row-major flattening is:

Table 110 Mapping of support points to flattened LUT_data_array entries#

x

y

row-major index

lut_data

0

0

0

0

1

0

1

1

2

0

2

2

0

1

3

10

1

1

4

11

2

1

5

12

0

2

6

20

1

2

7

21

2

2

8

22

If input_x or input_y is outside the breakpoint range, it is clamped to the nearest breakpoint. The return value is then computed with bilinear interpolation. If either input is NaN, the return value is also NaN.

Listing 98 Example initialization of the 2D LUT configuration#
        // Axis breakpoints
        static float LUT_breakpoints_x_array[3] = {0.0f, 1.0f, 2.0f};
        static float LUT_breakpoints_y_array[3] = {0.0f, 1.0f, 2.0f};

        // Flattened data in row-major order:
        // row y=0: {0, 1, 2}
        // row y=1: {10, 11, 12}
        // row y=2: {20, 21, 22}
        static float LUT_data_array[9] = {
                        0.0f, 1.0f, 2.0f,
                        10.0f, 11.0f, 12.0f,
                        20.0f, 21.0f, 22.0f
        };

        uz_array_float_t LUT_breakpoints_x = {
                        .length = UZ_ARRAY_SIZE(LUT_breakpoints_x_array),
                        .data = &LUT_breakpoints_x_array[0]
        };
        uz_array_float_t LUT_breakpoints_y = {
                        .length = UZ_ARRAY_SIZE(LUT_breakpoints_y_array),
                        .data = &LUT_breakpoints_y_array[0]
        };
        uz_array_float_t LUT_data = {
                        .length = UZ_ARRAY_SIZE(LUT_data_array),
                        .data = &LUT_data_array[0]
        };

        uz_LUT_2D_t *lut_instance = uz_LUT_2D_init(&LUT_breakpoints_x, &LUT_breakpoints_y, &LUT_data);
        float input_x = 0.5f;
        float input_y = 0.5f;
        float output = uz_LUT_2D_get_value(lut_instance, input_x, input_y); // output = 5.5

The following plot shows the LUT support points, the underlying surface grid, and one interpolation point.

Figure made with TikZ

Fig. 371 Example 2D LUT support grid for LUT_data_array. The red marker indicates \((x,y)=(0.5,0.5)\) with bilinear interpolation result \(f(0.5,0.5)=5.5\).

Reference#

typedef struct uz_LUT_2D_t uz_LUT_2D_t#
uz_LUT_2D_t *uz_LUT_2D_init(uz_array_float_t *breakpoints_x, uz_array_float_t *breakpoints_y, uz_array_float_t *data)#

Initializes a 2D Look-Up Table (LUT) instance with the provided breakpoints and grid data.

Data layout:

  • data is a flattened 2D array in row-major order

  • x-axis changes fastest

  • index = (y_index * breakpoints_x->length) + x_index

Preconditions:

  • breakpoints_x, breakpoints_y and data are not NULL

  • their data pointers are not NULL

  • both breakpoint arrays have length of at least 2

  • both breakpoint arrays are strictly increasing (no duplicates)

  • data length is breakpoints_x->length * breakpoints_y->length

Parameters:
  • breakpoints_x – pointer to x-axis breakpoints

  • breakpoints_y – pointer to y-axis breakpoints

  • data – pointer to flattened 2D grid values

Returns:

uz_LUT_2D_t*

float uz_LUT_2D_get_value(uz_LUT_2D_t *self, float input_x, float input_y)#

Returns a bilinearly interpolated LUT value at (input_x, input_y).

Inputs are clamped to the breakpoint ranges before interpolation. NaN inputs propagate through the interpolation and result in NaN.

Parameters:
  • self – instance of the LUT_2D

  • input_x – x-axis input value

  • input_y – y-axis input value

Returns:

float