__kernel void weighted_euclidean_batch(
  __global numeric* output,
  const unsigned int count,
  __global const numeric* input,
  __global const numeric* weights,
  const int N,
  const int DIM,
  const int batch_offset,
  const int batch_cols) {

  size_t local_row = get_global_id(0);
  size_t local_col = get_global_id(1);
  size_t row = ((size_t) batch_offset) + local_row;
  size_t col = ((size_t) batch_offset) + local_col;
  size_t rows = ((size_t) N) - ((size_t) batch_offset);
  size_t output_index = local_col * rows + local_row;

  if (row < (size_t) N && local_col < (size_t) batch_cols &&
      output_index < (size_t) count) {
    numeric sum = (numeric) 0;
    for (int k = 0; k < DIM; ++k) {
      size_t offset = ((size_t) k) * ((size_t) N);
      numeric diff = input[row + offset] - input[col + offset];
      sum += weights[k] * diff * diff;
    }
    output[output_index] = sqrt(sum);
  }
}
