static inline float colordiff (float4 pixA,
                               float4 pixB)
{
  float4 pix = pixA - pixB;
  pix *= pix;
  return pix.x + pix.y + pix.z;
}

__kernel void snn_mean (__global const   float4 *src_buf,
                                         int src_width,
                                         int src_height,
                        __global         float4 *dst_buf,
                                         int radius,
                                         int pairs)
{
  int gidx   = get_global_id(0);
  int gidy   = get_global_id(1);
  int offset = gidy * get_global_size(0) + gidx;

  const float4 center_pix  =
      *(src_buf + ((radius + gidx) + (gidy + radius) * src_width));
        float4 accumulated = 0;

  int count = 0;
  if (pairs == 2)
    {
      for (int i = -radius; i <= 0; i++)
        {
          for (int j = -radius; j <= 0 ; j++)
            {
              float4 selected_pix = center_pix;
              float  best_diff    = 1000.0f;

              if (i != 0 && j != 0)
                {
                  int xs[4] =
                    {
                      gidx + j + radius, gidx - j + radius,
                      gidx - j + radius, gidx + j + radius
                    };
                  int ys[4] =
                    {
                      gidy + i + radius, gidy - i + radius,
                      gidy + i + radius, gidy - i + radius
                    };

                  for (int k = 0; k < 4; k++)
                    {
                      if (xs[k] >= 0 && xs[k] < src_width &&
                          ys[k] >= 0 && ys[k] < src_height)
                        {
                          const float4 tpix =
                              *(src_buf + (xs[k] + ys[k] * src_width));
                                float  diff = colordiff (tpix, center_pix);
                          if (diff < best_diff)
                            {
                              best_diff    = diff;
                              selected_pix = tpix;
                            }
                        }
                    }
                }
              accumulated += selected_pix;
              ++count;
              if (i == 0 && j == 0)
                break;
            }
        }
      dst_buf[offset] = accumulated / (float4)(count);
      return;
    }
  else if (pairs == 1)
    {
      for (int i = -radius; i <= 0; i++)
        {
          for (int j = -radius; j <= radius; j++)
            {
              float4 selected_pix = center_pix;
              float  best_diff    = 1000.0f;

              /* skip computations for the center pixel */
              if (i != 0 && j != 0)
                {
                  int xs[4] =
                    {
                      gidx + j + radius, gidx - j + radius,
                      gidx - j + radius, gidx + j + radius
                    };
                  int ys[4] =
                    {
                      gidy + i + radius, gidy - i + radius,
                      gidy + i + radius, gidy - i + radius
                    };

                  for (int k = 0; k < 2; k++)
                    {
                      if (xs[k] >= 0 && xs[k] < src_width &&
                          ys[k] >= 0 && ys[k] < src_height)
                        {
                          const float4 tpix =
                              *(src_buf + (xs[k] + ys[k] * src_width));
                                float  diff = colordiff (tpix, center_pix);
                          if (diff < best_diff)
                            {
                              best_diff    = diff;
                              selected_pix = tpix;
                            }
                        }
                    }
                }
              accumulated += selected_pix;
              ++count;
              if (i == 0 && j == 0)
                 break;
            }
        }
      dst_buf[offset] = accumulated / (float4)(count);
      return;
    }
  return;
}
