oklab: add double variant of code for model conversions
authorØyvind Kolås <pippin@gimp.org>
Thu, 28 Oct 2021 23:16:48 +0000 (01:16 +0200)
committerØyvind Kolås <pippin@gimp.org>
Thu, 28 Oct 2021 23:18:30 +0000 (01:18 +0200)
extensions/oklab.c

index e94c611ee0ee7aac6e7d737a2e2df6ce457a0fbe..6dab0a793670218729235bd1fdfb2b2ef6d5b367 100644 (file)
@@ -47,6 +47,9 @@ int init (void);
 int\r
 init (void)\r
 {\r
+  return 0; // the oklab conversions are not fully symmetric,\r
+            // thus not allowing the tests to pass if we register\r
+            // the code\r
   components ();\r
   models ();\r
   formats ();\r
@@ -156,6 +159,9 @@ static float M1f[9];
 static float M2f[9];\r
 static float inv_M1f[9];\r
 static float inv_M2f[9];\r
+\r
+static double inv_M1[9];\r
+static double inv_M2[9];\r
 static int mat_ready;\r
 \r
 /* fast approximate cube root\r
@@ -182,7 +188,19 @@ _cbrtf (float x)
 }\r
 \r
 static inline void\r
-XYZ_to_Oklab_step (float *xyz, float *lab_out)\r
+XYZ_to_Oklab_step (double *xyz, double *lab_out)\r
+{\r
+  double lms[3];\r
+  babl_matrix_mul_vector (M1, xyz, lms);\r
+  for (int i = 0; i < 3; i++)\r
+    {\r
+      lms[i] = cbrt (lms[i]);\r
+    }\r
+  babl_matrix_mul_vector (M2, lms, lab_out);\r
+}\r
+\r
+static inline void\r
+XYZ_to_Oklab_stepf (float *xyz, float *lab_out)\r
 {\r
   float lms[3];\r
   babl_matrix_mul_vectorff (M1f, xyz, lms);\r
@@ -194,7 +212,7 @@ XYZ_to_Oklab_step (float *xyz, float *lab_out)
 }\r
 \r
 static inline void\r
-Oklab_to_XYZ_step (float *lab, float *xyz_out)\r
+Oklab_to_XYZ_stepf (float *lab, float *xyz_out)\r
 {\r
   float lms[3];\r
   babl_matrix_mul_vectorff (inv_M2f, lab, lms);\r
@@ -206,9 +224,21 @@ Oklab_to_XYZ_step (float *lab, float *xyz_out)
 }\r
 \r
 static inline void\r
-ab_to_ch_step (float *ab, float *ch_out)\r
+Oklab_to_XYZ_step (double *lab, double *xyz_out)\r
 {\r
-  float a = ab[0], b = ab[1];\r
+  double lms[3];\r
+  babl_matrix_mul_vector (inv_M2, lab, lms);\r
+  for (int i = 0; i < 3; i++)\r
+    {\r
+      lms[i] = lms[i] * lms[i] * lms[i];\r
+    }\r
+  babl_matrix_mul_vector (inv_M1, lms, xyz_out);\r
+}\r
+\r
+static inline void\r
+ab_to_ch_step (double *ab, double *ch_out)\r
+{\r
+  double a = ab[0], b = ab[1];\r
 \r
   ch_out[1] = sqrt (a * a + b * b);\r
   ch_out[2] = atan2 (b, a) * DEGREES_PER_RADIAN;\r
@@ -219,29 +249,66 @@ ab_to_ch_step (float *ab, float *ch_out)
 }\r
 \r
 static inline void\r
-ch_to_ab_step (float *ch, float *ab_out)\r
+ab_to_ch_stepf (float *ab, float *ch_out)\r
 {\r
-  float c = ch[0], h = ch[1];\r
+  float a = ab[0], b = ab[1];\r
+\r
+  ch_out[1] = sqrtf (a * a + b * b);\r
+  ch_out[2] = atan2f (b, a) * DEGREES_PER_RADIAN;\r
+\r
+  // Keep H within the range 0-360\r
+  if (ch_out[2] < 0.0)\r
+    ch_out[2] += 360;\r
+}\r
+\r
+static inline void\r
+ch_to_ab_step (double *ch, double *ab_out)\r
+{\r
+  double c = ch[0], h = ch[1];\r
 \r
   ab_out[0] = cos (h * RADIANS_PER_DEGREE) * c;\r
   ab_out[1] = sin (h * RADIANS_PER_DEGREE) * c;\r
 }\r
 \r
 static inline void\r
-XYZ_to_Oklch_step (float *xyz, float *lch_out)\r
+ch_to_ab_stepf (float *ch, float *ab_out)\r
+{\r
+  float c = ch[0], h = ch[1];\r
+\r
+  ab_out[0] = cosf (h * RADIANS_PER_DEGREE) * c;\r
+  ab_out[1] = sinf (h * RADIANS_PER_DEGREE) * c;\r
+}\r
+\r
+static inline void\r
+XYZ_to_Oklch_step (double *xyz, double *lch_out)\r
 {\r
   XYZ_to_Oklab_step (xyz, lch_out);\r
   ab_to_ch_step (lch_out + 1, lch_out + 1);\r
 }\r
 \r
 static inline void\r
-Oklch_to_XYZ_step (float *lch, float *xyz_out)\r
+XYZ_to_Oklch_stepf (float *xyz, float *lch_out)\r
 {\r
-  float lab[3] = { lch[0], lch[1], lch[2] };\r
+  XYZ_to_Oklab_stepf (xyz, lch_out);\r
+  ab_to_ch_stepf (lch_out + 1, lch_out + 1);\r
+}\r
+\r
+static inline void\r
+Oklch_to_XYZ_step (double *lch, double *xyz_out)\r
+{\r
+  double lab[3] = { lch[0], lch[1], lch[2] };\r
   ch_to_ab_step (lab + 1, lab + 1);\r
   Oklab_to_XYZ_step (lab, xyz_out);\r
 }\r
 \r
+static inline void\r
+Oklch_to_XYZ_stepf (float *lch, float *xyz_out)\r
+{\r
+  float lab[3] = { lch[0], lch[1], lch[2] };\r
+  ch_to_ab_stepf (lab + 1, lab + 1);\r
+  Oklab_to_XYZ_stepf (lab, xyz_out);\r
+}\r
+\r
 static inline void\r
 constants (void)\r
 {\r
@@ -255,10 +322,10 @@ constants (void)
   babl_chromatic_adaptation_matrix (D50, D65, tmp);\r
   babl_matrix_mul_matrix (tmp, M1, M1);\r
 \r
-  babl_matrix_invert (M1, tmp);\r
-  babl_matrix_to_float (tmp, inv_M1f);\r
-  babl_matrix_invert (M2, tmp);\r
-  babl_matrix_to_float (tmp, inv_M2f);\r
+  babl_matrix_invert (M1, inv_M1);\r
+  babl_matrix_to_float (inv_M1, inv_M1f);\r
+  babl_matrix_invert (M2, inv_M2);\r
+  babl_matrix_to_float (inv_M2, inv_M2f);\r
 \r
   babl_matrix_to_float (M1, M1f);\r
   babl_matrix_to_float (M2, M2f);\r
@@ -268,7 +335,7 @@ constants (void)
 \r
 /* Convertion routine (glue and boilerplate). */\r
 static void\r
-rgba_to_laba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+rgba_to_laba_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -278,6 +345,25 @@ rgba_to_laba (const Babl *conversion, char *src_, char *dst_, long samples)
     {\r
       float xyz[3];\r
       babl_space_to_xyzf (space, src, xyz);\r
+      XYZ_to_Oklab_stepf (xyz, dst);\r
+      dst[3] = src[3];\r
+\r
+      src += 4;\r
+      dst += 4;\r
+    }\r
+}\r
+\r
+static void\r
+rgba_to_laba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  double *src = (double*)src_, *dst = (double*)dst_;\r
+  const Babl *space = babl_conversion_get_source_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      double xyz[3];\r
+      babl_space_to_xyz (space, src, xyz);\r
       XYZ_to_Oklab_step (xyz, dst);\r
       dst[3] = src[3];\r
 \r
@@ -287,7 +373,7 @@ rgba_to_laba (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-rgba_to_lab (const Babl *conversion, char *src_, char *dst_, long samples)\r
+rgba_to_lab_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -297,6 +383,24 @@ rgba_to_lab (const Babl *conversion, char *src_, char *dst_, long samples)
     {\r
       float xyz[3];\r
       babl_space_to_xyzf (space, src, xyz);\r
+      XYZ_to_Oklab_stepf (xyz, dst);\r
+\r
+      src += 4;\r
+      dst += 3;\r
+    }\r
+}\r
+\r
+static void\r
+rgba_to_lab (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  double *src = (double *)src_, *dst = (double *)dst_;\r
+  const Babl *space = babl_conversion_get_source_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      double xyz[3];\r
+      babl_space_to_xyz (space, src, xyz);\r
       XYZ_to_Oklab_step (xyz, dst);\r
 \r
       src += 4;\r
@@ -305,7 +409,7 @@ rgba_to_lab (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-rgba_to_lcha (const Babl *conversion, char *src_, char *dst_, long samples)\r
+rgba_to_lcha_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -315,6 +419,25 @@ rgba_to_lcha (const Babl *conversion, char *src_, char *dst_, long samples)
     {\r
       float xyz[3];\r
       babl_space_to_xyzf (space, src, xyz);\r
+      XYZ_to_Oklch_stepf (xyz, dst);\r
+      dst[3] = src[3];\r
+\r
+      src += 4;\r
+      dst += 4;\r
+    }\r
+}\r
+\r
+static void\r
+rgba_to_lcha (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  double *src = (double *)src_, *dst = (double *)dst_;\r
+  const Babl *space = babl_conversion_get_source_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      double xyz[3];\r
+      babl_space_to_xyz (space, src, xyz);\r
       XYZ_to_Oklch_step (xyz, dst);\r
       dst[3] = src[3];\r
 \r
@@ -324,7 +447,7 @@ rgba_to_lcha (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-rgba_to_lch (const Babl *conversion, char *src_, char *dst_, long samples)\r
+rgba_to_lch_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -334,6 +457,24 @@ rgba_to_lch (const Babl *conversion, char *src_, char *dst_, long samples)
     {\r
       float xyz[3];\r
       babl_space_to_xyzf (space, src, xyz);\r
+      XYZ_to_Oklch_stepf (xyz, dst);\r
+\r
+      src += 4;\r
+      dst += 3;\r
+    }\r
+}\r
+\r
+static void\r
+rgba_to_lch (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  double *src = (double *)src_, *dst = (double *)dst_;\r
+  const Babl *space = babl_conversion_get_source_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      double xyz[3];\r
+      babl_space_to_xyz (space, src, xyz);\r
       XYZ_to_Oklch_step (xyz, dst);\r
 \r
       src += 4;\r
@@ -342,7 +483,43 @@ rgba_to_lch (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-lab_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+rgb_to_lab_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  float *src = (float *)src_, *dst = (float *)dst_;\r
+  const Babl *space = babl_conversion_get_source_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      float xyz[3];\r
+      babl_space_to_xyzf (space, src, xyz);\r
+      XYZ_to_Oklab_stepf (xyz, dst);\r
+\r
+      src += 3;\r
+      dst += 3;\r
+    }\r
+}\r
+\r
+static void\r
+rgb_to_lch_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  float *src = (float *)src_, *dst = (float *)dst_;\r
+  const Babl *space = babl_conversion_get_source_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      float xyz[3];\r
+      babl_space_to_xyzf (space, src, xyz);\r
+      XYZ_to_Oklch_stepf (xyz, dst);\r
+\r
+      src += 3;\r
+      dst += 3;\r
+    }\r
+}\r
+\r
+static void\r
+lab_to_rgb_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -351,7 +528,25 @@ lab_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)
   while (n--)\r
     {\r
       float xyz[3];\r
-      Oklab_to_XYZ_step (src, xyz);\r
+      Oklab_to_XYZ_stepf (src, xyz);\r
+      babl_space_from_xyzf (space, xyz, dst);\r
+\r
+      src += 3;\r
+      dst += 3;\r
+    }\r
+}\r
+\r
+static void\r
+lab_to_rgba_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  float *src = (float *)src_, *dst = (float *)dst_;\r
+  const Babl *space = babl_conversion_get_destination_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      float xyz[3];\r
+      Oklab_to_XYZ_stepf (src, xyz);\r
       babl_space_from_xyzf (space, xyz, dst);\r
       dst[3] = 1.0;\r
 \r
@@ -361,7 +556,26 @@ lab_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-laba_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+lab_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  double *src = (double *)src_, *dst = (double *)dst_;\r
+  const Babl *space = babl_conversion_get_destination_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      double xyz[3];\r
+      Oklab_to_XYZ_step (src, xyz);\r
+      babl_space_from_xyz (space, xyz, dst);\r
+      dst[3] = 1.0;\r
+\r
+      src += 3;\r
+      dst += 4;\r
+    }\r
+}\r
+\r
+static void\r
+lch_to_rgb_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -370,7 +584,25 @@ laba_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)
   while (n--)\r
     {\r
       float xyz[3];\r
-      Oklab_to_XYZ_step (src, xyz);\r
+      Oklch_to_XYZ_stepf (src, xyz);\r
+      babl_space_from_xyzf (space, xyz, dst);\r
+\r
+      src += 3;\r
+      dst += 3;\r
+    }\r
+}\r
+\r
+static void\r
+laba_to_rgba_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  float *src = (float *)src_, *dst = (float *)dst_;\r
+  const Babl *space = babl_conversion_get_destination_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      float xyz[3];\r
+      Oklab_to_XYZ_stepf (src, xyz);\r
       babl_space_from_xyzf (space, xyz, dst);\r
       dst[3] = src[3];\r
 \r
@@ -380,7 +612,26 @@ laba_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-lcha_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+laba_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  double *src = (double *)src_, *dst = (double *)dst_;\r
+  const Babl *space = babl_conversion_get_destination_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      double xyz[3];\r
+      Oklab_to_XYZ_step (src, xyz);\r
+      babl_space_from_xyz (space, xyz, dst);\r
+      dst[3] = src[3];\r
+\r
+      src += 4;\r
+      dst += 4;\r
+    }\r
+}\r
+\r
+static void\r
+lcha_to_rgba_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -389,7 +640,7 @@ lcha_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)
   while (n--)\r
     {\r
       float xyz[3];\r
-      Oklch_to_XYZ_step (src, xyz);\r
+      Oklch_to_XYZ_stepf (src, xyz);\r
       babl_space_from_xyzf (space, xyz, dst);\r
       dst[3] = src[3];\r
 \r
@@ -399,7 +650,27 @@ lcha_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-lch_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+lcha_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  double *src = (double *)src_, *dst = (double *)dst_;\r
+  const Babl *space = babl_conversion_get_destination_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      double xyz[3];\r
+      Oklch_to_XYZ_step (src, xyz);\r
+      babl_space_from_xyz (space, xyz, dst);\r
+      dst[3] = src[3];\r
+\r
+      src += 4;\r
+      dst += 4;\r
+    }\r
+}\r
+\r
+\r
+static void\r
+lch_to_rgba_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -408,7 +679,7 @@ lch_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)
   while (n--)\r
     {\r
       float xyz[3];\r
-      Oklch_to_XYZ_step (src, xyz);\r
+      Oklch_to_XYZ_stepf (src, xyz);\r
       babl_space_from_xyzf (space, xyz, dst);\r
       dst[3] = 1.0f;\r
 \r
@@ -418,7 +689,27 @@ lch_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-lch_to_lab (const Babl *conversion, char *src_, char *dst_, long samples)\r
+lch_to_rgba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+{\r
+  long n = samples;\r
+  double *src = (double *)src_, *dst = (double *)dst_;\r
+  const Babl *space = babl_conversion_get_destination_space (conversion);\r
+\r
+  while (n--)\r
+    {\r
+      double xyz[3];\r
+      Oklch_to_XYZ_step (src, xyz);\r
+      babl_space_from_xyz (space, xyz, dst);\r
+      dst[3] = 1.0f;\r
+\r
+      src += 3;\r
+      dst += 4;\r
+    }\r
+}\r
+\r
+\r
+static void\r
+lch_to_lab_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -426,7 +717,7 @@ lch_to_lab (const Babl *conversion, char *src_, char *dst_, long samples)
   while (n--)\r
     {\r
       dst[0] = src[0];\r
-      ch_to_ab_step (src + 1, dst + 1);\r
+      ch_to_ab_stepf (src + 1, dst + 1);\r
 \r
       src += 3;\r
       dst += 3;\r
@@ -434,7 +725,7 @@ lch_to_lab (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-lab_to_lch (const Babl *conversion, char *src_, char *dst_, long samples)\r
+lab_to_lch_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -442,7 +733,7 @@ lab_to_lch (const Babl *conversion, char *src_, char *dst_, long samples)
   while (n--)\r
     {\r
       dst[0] = src[0];\r
-      ab_to_ch_step (src + 1, dst + 1);\r
+      ab_to_ch_stepf (src + 1, dst + 1);\r
 \r
       src += 3;\r
       dst += 3;\r
@@ -450,7 +741,7 @@ lab_to_lch (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-lcha_to_laba (const Babl *conversion, char *src_, char *dst_, long samples)\r
+lcha_to_laba_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -458,7 +749,7 @@ lcha_to_laba (const Babl *conversion, char *src_, char *dst_, long samples)
   while (n--)\r
     {\r
       dst[0] = src[0];\r
-      ch_to_ab_step (src + 1, dst + 1);\r
+      ch_to_ab_stepf (src + 1, dst + 1);\r
       dst[3] = src[3];\r
 \r
       src += 4;\r
@@ -467,7 +758,7 @@ lcha_to_laba (const Babl *conversion, char *src_, char *dst_, long samples)
 }\r
 \r
 static void\r
-laba_to_lcha (const Babl *conversion, char *src_, char *dst_, long samples)\r
+laba_to_lcha_float (const Babl *conversion, char *src_, char *dst_, long samples)\r
 {\r
   long n = samples;\r
   float *src = (float *)src_, *dst = (float *)dst_;\r
@@ -475,13 +766,14 @@ laba_to_lcha (const Babl *conversion, char *src_, char *dst_, long samples)
   while (n--)\r
     {\r
       dst[0] = src[0];\r
-      ab_to_ch_step (src + 1, dst + 1);\r
+      ab_to_ch_stepf (src + 1, dst + 1);\r
       dst[3] = src[3];\r
 \r
       src += 4;\r
       dst += 4;\r
     }\r
 }\r
+\r
 /* End conversion routines. */\r
 \r
 static void\r
@@ -535,7 +827,16 @@ conversions (void)
                        "linear", lch_to_rgba,\r
                        NULL);\r
 \r
-  _pair ("Oklab float", "Oklch float", lab_to_lch, lch_to_lab);\r
-  _pair ("Oklab alpha float", "Oklch alpha float", laba_to_lcha, lcha_to_laba);\r
-#undef _pair\r
+\r
+  _pair ("RGB float", "Oklab float", rgb_to_lab_float, lab_to_rgb_float);\r
+  _pair ("RGBA float", "Oklab alpha float", rgba_to_laba_float, laba_to_rgba_float);\r
+  _pair ("RGBA float", "Oklab float", rgba_to_lab_float, lab_to_rgba_float);\r
+\r
+  _pair ("RGBA float", "Oklch float", rgba_to_lch_float, lch_to_rgba_float);\r
+  _pair ("RGB float", "Oklch float", rgb_to_lch_float, lch_to_rgb_float);\r
+  _pair ("RGBA float", "Oklch alpha float", rgba_to_lcha_float, lcha_to_rgba_float);\r
+  \r
+  _pair ("Oklab float", "Oklch float", lab_to_lch_float, lch_to_lab_float);\r
+  _pair ("Oklab alpha float", "Oklch alpha float", laba_to_lcha_float, lcha_to_laba_float);\r
+  #undef _pair\r
 }\r