static const char* noise_hsv_cl_source =
"/* This file is an image processing operation for GEGL                        \n"
" *                                                                            \n"
" * GEGL is free software; you can redistribute it and/or                      \n"
" * modify it under the terms of the GNU Lesser General Public                 \n"
" * License as published by the Free Software Foundation; either               \n"
" * version 3 of the License, or (at your option) any later version.           \n"
" *                                                                            \n"
" * GEGL is distributed in the hope that it will be useful,                    \n"
" * but WITHOUT ANY WARRANTY; without even the implied warranty of             \n"
" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU          \n"
" * Lesser General Public License for more details.                            \n"
" *                                                                            \n"
" * You should have received a copy of the GNU Lesser General Public           \n"
" * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.      \n"
" *                                                                            \n"
" */                                                                           \n"
"                                                                              \n"
"float                                                                         \n"
"randomize_value (__global const int        *random_data,                      \n"
"                          const GeglRandom  rand,                             \n"
"                                float       now,                              \n"
"                                float       min_val,                          \n"
"                                float       max_val,                          \n"
"                                bool        wraps_around,                     \n"
"                                float       rand_max,                         \n"
"                                int         holdness,                         \n"
"                                int         x,                                \n"
"                                int         y,                                \n"
"                                int         n)                                \n"
"{                                                                             \n"
"  const float steps = max_val - min_val;                                      \n"
"  float rand_val = gegl_cl_random_float (random_data, rand, x, y, 0, n++);    \n"
"                                                                              \n"
"  for (int i = 1; i < holdness; i++)                                          \n"
"    {                                                                         \n"
"      float tmp = gegl_cl_random_float (random_data, rand, x, y, 0, n++);     \n"
"      rand_val = min (rand_val, tmp);                                         \n"
"    }                                                                         \n"
"                                                                              \n"
"  const int flag = (gegl_cl_random_float (random_data, rand, x, y, 0, n) < 0.5)\n"
"                   ? -1 : 1;                                                  \n"
"  float new_val = now + flag * fmod (rand_max * rand_val, steps);             \n"
"                                                                              \n"
"  if (new_val < min_val)                                                      \n"
"    {                                                                         \n"
"      if (wraps_around)                                                       \n"
"        new_val += steps;                                                     \n"
"      else                                                                    \n"
"        new_val = min_val;                                                    \n"
"    }                                                                         \n"
"                                                                              \n"
"  if (max_val < new_val)                                                      \n"
"    {                                                                         \n"
"      if (wraps_around)                                                       \n"
"        new_val -= steps;                                                     \n"
"      else                                                                    \n"
"        new_val = max_val;                                                    \n"
"    }                                                                         \n"
"                                                                              \n"
"  return new_val;                                                             \n"
"}                                                                             \n"
"                                                                              \n"
"__kernel void cl_noise_hsv(__global const float4    *in,                      \n"
"                           __global       float4    *out,                     \n"
"                           __global const int       *random_data,             \n"
"                                    const GeglRandom rand,                    \n"
"                                          int        x_offset,                \n"
"                                          int        y_offset,                \n"
"                                          int        roi_width,               \n"
"                                          int        whole_region_width,      \n"
"                                          int        holdness,                \n"
"                                          float      hue_distance,            \n"
"                                          float      saturation_distance,     \n"
"                                          float      value_distance)          \n"
"{                                                                             \n"
"  const int gid  = get_global_id(0);                                          \n"
"  const int gidy = gid / roi_width;                                           \n"
"  const int gidx = gid - gidy * roi_width;                                    \n"
"                                                                              \n"
"  const int x = gidx + x_offset;                                              \n"
"  const int y = gidy + y_offset;                                              \n"
"                                                                              \n"
"  int n = (3 * holdness + 4) * (x + whole_region_width * y);                  \n"
"                                                                              \n"
"  const float4 in_v = in[gid];                                                \n"
"                                                                              \n"
"  float hue        = in_v.s0;                                                 \n"
"  float saturation = in_v.s1;                                                 \n"
"  float value      = in_v.s2;                                                 \n"
"  float alpha      = in_v.s3;                                                 \n"
"                                                                              \n"
"  /* there is no need for scattering hue of desaturated pixels here */        \n"
"  if ((hue_distance > 0) && (saturation > 0))                                 \n"
"    hue = randomize_value (random_data, rand,                                 \n"
"                           hue, 0.0, 1.0, true,                               \n"
"                           hue_distance, holdness,                            \n"
"                           x, y, n);                                          \n"
"                                                                              \n"
"  n += holdness + 1;                                                          \n"
"  if (saturation_distance > 0)                                                \n"
"    {                                                                         \n"
"      /* desaturated pixels get random hue before increasing saturation */    \n"
"      if (saturation == 0)                                                    \n"
"        hue = gegl_cl_random_float_range (random_data, rand,                  \n"
"                                          x, y, 0, n, 0.0, 1.0);              \n"
"      saturation = randomize_value (random_data, rand,                        \n"
"                                    saturation, 0.0, 1.0, false,              \n"
"                                    saturation_distance, holdness,            \n"
"                                    x, y, n + 1);                             \n"
"    }                                                                         \n"
"                                                                              \n"
"  n += holdness + 2;                                                          \n"
"  if (value_distance > 0)                                                     \n"
"    value = randomize_value (random_data, rand,                               \n"
"                             value, 0.0, 1.0, false,                          \n"
"                             value_distance, holdness,                        \n"
"                             x, y, n);                                        \n"
"                                                                              \n"
"  out[gid] = (float4)(hue, saturation, value, alpha);                         \n"
"}                                                                             \n"
;
