I try to compute the lightness of an RGB pixel with various methods, in C99 with GCC 9. I have this enum :
typedef enum dt_iop_toneequalizer_method_t
{
  DT_TONEEQ_MEAN = 0,
  DT_TONEEQ_LIGHTNESS,
  DT_TONEEQ_VALUE
} dt_iop_toneequalizer_method_t;
which is user input from a GUI.
Then, I have several functions corresponding to each case:
typedef float rgb_pixel[4] __attribute__((aligned(16)));
#pragma omp declare simd aligned(pixel:64)
static float _RGB_mean(const rgb_pixel pixel)
{
  return (pixel[0] + pixel[1] + pixel[2] + pixel[3]) / 3.0f;
}
#pragma omp declare simd aligned(pixel:16)
static float _RGB_value(const rgb_pixel pixel)
{
  return fmaxf(fmaxf(pixel[0], pixel[1]), pixel[2]);
}
#pragma omp declare simd aligned(pixel:16)
static float _RGB_lightness(const rgb_pixel pixel)
{
  const float max_rgb = _RGB_value(pixel);
  const float min_rgb = fminf(pixel[0], fminf(pixel[1], pixel[2]));
  return (max_rgb + min_rgb) / 2.0f;
}
Then, the loop over the image is:
static void exposure_mask(const float *const restrict in, 
                          float *const restrict out,
                          const size_t width, 
                          const size_t height, 
                          const dt_iop_toneequalizer_method_t method)
{
#pragma omp parallel for simd default(none) schedule(static) aligned(in, out:64)
  for(size_t k = 0; k < 4 * width * height; k += 4)
  {
    const rgb_pixel pixel = { in[k], in[k + 1], in[k + 2], 0.0f };
    out[k / 4] = RGB_light(pixel, method);
  }
}
My first approach was to use an RGB_light() function with a switch/case mapping the method and the functions, but that triggers checks for every pixel, which is quite expensive. 
My idea would be to use a list or a struct of the methods, like that:
typedef struct RGB_light
{
  // Pixel intensity (method == DT_TONEEQ_MEAN)
  float (*_RGB_mean)(rgb_pixel pixel);
  // Pixel HSL lightness (method == DT_TONEEQ_LIGHTNESS)
  float (*_RGB_lightness)(rgb_pixel pixel);
  // Pixel HSV value (method == DT_TONEEQ_VALUE)
  float (*_RGB_value)(rgb_pixel pixel);
} RGB_light;
then initiatize the method once for all before the loop, like
static void exposure_mask(const float *const restrict in, 
                          float *const restrict out,
                          const size_t width, 
                          const size_t height, 
                          const dt_iop_toneequalizer_method_t method)
{
  lightness_method = RGB_light[method]; // obviously wrong syntax
#pragma omp parallel for simd default(none) schedule(static) aligned(in, out:64)
  for(size_t k = 0; k < 4 * width * height; k += 4)
  {
    const rgb_pixel pixel = { in[k], in[k + 1], in[k + 2], 0.0f };
    out[k / 4] = lightness_method(pixel);
  }
}
but I did not succeed in translating that idea to actual working code.
There is something similar to what I want to do in Python :
def RGB_value(pixel):
  return whatever
def RGB_lightness(pixel):
  return whatever
methods = { 1: RGB_value, 2: RGB_lightness }
def loop(image, method):
  for pixel in image:
    lightness = methods[method](pixel)
 
    