tidy up skcms_internal.h

Lots of things are now static in skcms.c.

I also removed the debug-mode profiling feature.

The only thing I really was on the fence about was removing
the unit test for isfinite_().  Seems nice, but on the other
hand, kind of hard for us to get isfinite_() wrong.  In C++11
I think we could make this constexpr and tested at compile time
with static_assert, so maybe just put off worrying until then?

Change-Id: I1ae326bad8fa6924245444521f8bd2d1e7d1bed1
Reviewed-on: https://skia-review.googlesource.com/138939
Commit-Queue: Mike Klein <mtklein@chromium.org>
Auto-Submit: Mike Klein <mtklein@chromium.org>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/bench.c b/bench.c
index 53a4ffb..64ce3c8 100644
--- a/bench.c
+++ b/bench.c
@@ -43,8 +43,6 @@
 static float src_pixels[NPIXELS * 4],
              dst_pixels[NPIXELS * 4];
 
-extern bool g_skcms_dump_profile;
-
 int main(int argc, char** argv) {
     int           n = 100000;
     const char* src = "profiles/mobile/sRGB_parametric.icc";
@@ -54,7 +52,6 @@
         if (0 == strcmp(argv[i], "-n")) { n   = atoi(argv[++i]); }
         if (0 == strcmp(argv[i], "-s")) { src =      argv[++i] ; }
         if (0 == strcmp(argv[i], "-d")) { dst =      argv[++i] ; }
-        if (0 == strcmp(argv[i], "-p")) { g_skcms_dump_profile = true; }
     }
 
     void  *src_buf, *dst_buf;
diff --git a/skcms.c b/skcms.c
index 5b66128..ddcd02e 100644
--- a/skcms.c
+++ b/skcms.c
@@ -13,6 +13,24 @@
 #include <stdlib.h>
 #include <string.h>
 
+// sizeof(x) will return size_t, which is 32-bit on some machines and 64-bit on others.
+// We have better testing on 64-bit machines, so force 32-bit machines to behave like 64-bit.
+//
+// Please do not use sizeof() directly, and size_t only when required.
+// (We have no way of enforcing these requests...)
+#define SAFE_SIZEOF(x) ((uint64_t)sizeof(x))
+
+static const union {
+    uint32_t bits;
+    float    f;
+} inf_ = { 0x7f800000 };
+#define INFINITY_ inf_.f
+
+static float fmaxf_(float x, float y) { return x > y ? x : y; }
+static float fminf_(float x, float y) { return x < y ? x : y; }
+
+static bool isfinitef_(float x) { return 0 == x*0; }
+
 static float minus_1_ulp(float x) {
     int32_t bits;
     memcpy(&bits, &x, sizeof(bits));
@@ -21,7 +39,7 @@
     return x;
 }
 
-float skcms_eval_curve(const skcms_Curve* curve, float x) {
+static float eval_curve(const skcms_Curve* curve, float x) {
     if (curve->table_entries == 0) {
         return skcms_TransferFunction_eval(&curve->parametric, x);
     }
@@ -47,20 +65,20 @@
     return l + (h-l)*t;
 }
 
-float skcms_MaxRoundtripError(const skcms_Curve* curve, const skcms_TransferFunction* inv_tf) {
+static float max_roundtrip_error(const skcms_Curve* curve, const skcms_TransferFunction* inv_tf) {
     uint32_t N = curve->table_entries > 256 ? curve->table_entries : 256;
     const float dx = 1.0f / (N - 1);
     float err = 0;
     for (uint32_t i = 0; i < N; i++) {
         float x = i * dx,
-              y = skcms_eval_curve(curve, x);
+              y = eval_curve(curve, x);
         err = fmaxf_(err, fabsf_(x - skcms_TransferFunction_eval(inv_tf, y)));
     }
     return err;
 }
 
 bool skcms_AreApproximateInverses(const skcms_Curve* curve, const skcms_TransferFunction* inv_tf) {
-    return skcms_MaxRoundtripError(curve, inv_tf) < (1/512.0f);
+    return max_roundtrip_error(curve, inv_tf) < (1/512.0f);
 }
 
 // Additional ICC signature values that are only used internally
@@ -215,6 +233,20 @@
            read_tag_xyz(bXYZ, &toXYZ->vals[0][2], &toXYZ->vals[1][2], &toXYZ->vals[2][2]);
 }
 
+static bool tf_is_valid(const skcms_TransferFunction* tf) {
+    // Reject obviously malformed inputs
+    if (!isfinitef_(tf->a + tf->b + tf->c + tf->d + tf->e + tf->f + tf->g)) {
+        return false;
+    }
+
+    // All of these parameters should be non-negative
+    if (tf->a < 0 || tf->c < 0 || tf->d < 0 || tf->g < 0) {
+        return false;
+    }
+
+    return true;
+}
+
 typedef struct {
     uint8_t type          [4];
     uint8_t reserved_a    [4];
@@ -289,7 +321,7 @@
             curve->parametric.f = read_big_fixed(paraTag->parameters + 24);
             break;
     }
-    return skcms_TransferFunction_isValid(&curve->parametric);
+    return tf_is_valid(&curve->parametric);
 }
 
 typedef struct {
@@ -679,6 +711,50 @@
     return true;
 }
 
+static int fit_linear(const skcms_Curve* curve, int N, float tol, float* c, float* d, float* f) {
+    assert(N > 1);
+    // We iteratively fit the first points to the TF's linear piece.
+    // We want the cx + f line to pass through the first and last points we fit exactly.
+    //
+    // As we walk along the points we find the minimum and maximum slope of the line before the
+    // error would exceed our tolerance.  We stop when the range [slope_min, slope_max] becomes
+    // emtpy, when we definitely can't add any more points.
+    //
+    // Some points' error intervals may intersect the running interval but not lie fully
+    // within it.  So we keep track of the last point we saw that is a valid end point candidate,
+    // and once the search is done, back up to build the line through *that* point.
+    const float dx = 1.0f / (N - 1);
+
+    int lin_points = 1;
+    *f = eval_curve(curve, 0);
+
+    float slope_min = -INFINITY_;
+    float slope_max = +INFINITY_;
+    for (int i = 1; i < N; ++i) {
+        float x = i * dx;
+        float y = eval_curve(curve, x);
+
+        float slope_max_i = (y + tol - *f) / x,
+              slope_min_i = (y - tol - *f) / x;
+        if (slope_max_i < slope_min || slope_max < slope_min_i) {
+            // Slope intervals would no longer overlap.
+            break;
+        }
+        slope_max = fminf_(slope_max, slope_max_i);
+        slope_min = fmaxf_(slope_min, slope_min_i);
+
+        float cur_slope = (y - *f) / x;
+        if (slope_min <= cur_slope && cur_slope <= slope_max) {
+            lin_points = i + 1;
+            *c = cur_slope;
+        }
+    }
+
+    // Set D to the last point that met our tolerance.
+    *d = (lin_points - 1) * dx;
+    return lin_points;
+}
+
 static bool read_a2b(const skcms_ICCTag* tag, skcms_A2B* a2b, bool pcs_is_xyz) {
     bool ok = false;
     if (tag->type == skcms_Signature_mft1) {
@@ -713,7 +789,7 @@
             int N = (int)curve->table_entries;
 
             float c,d,f;
-            if (N == skcms_fit_linear(curve, N, 1.0f/(2*N), &c,&d,&f)
+            if (N == fit_linear(curve, N, 1.0f/(2*N), &c,&d,&f)
                 && c == 1.0f
                 && f == 0.0f) {
                 curve->table_entries = 0;
@@ -1035,6 +1111,18 @@
     return 0 <= x && x <= 1;
 }
 
+typedef struct { float vals[3]; } skcms_Vector3;
+
+static skcms_Vector3 mv_mul(const skcms_Matrix3x3* m, const skcms_Vector3* v) {
+    skcms_Vector3 dst = {{0,0,0}};
+    for (int row = 0; row < 3; ++row) {
+        dst.vals[row] = m->vals[row][0] * v->vals[0]
+                      + m->vals[row][1] * v->vals[1]
+                      + m->vals[row][2] * v->vals[2];
+    }
+    return dst;
+}
+
 bool skcms_PrimariesToXYZD50(float rx, float ry,
                              float gx, float gy,
                              float bx, float by,
@@ -1061,7 +1149,7 @@
 
     // Assumes that Y is 1.0f.
     skcms_Vector3 wXYZ = { { wx / wy, 1, (1 - wx - wy) / wy } };
-    skcms_Vector3 XYZ = skcms_MV_mul(&primaries_inv, &wXYZ);
+    skcms_Vector3 XYZ = mv_mul(&primaries_inv, &wXYZ);
 
     skcms_Matrix3x3 toXYZ = {{
         { XYZ.vals[0],           0,           0 },
@@ -1087,8 +1175,8 @@
         { -0.0085287f,  0.0400428f, 0.9684867f },
     }};
 
-    skcms_Vector3 srcCone = skcms_MV_mul(&xyz_to_lms, &wXYZ);
-    skcms_Vector3 dstCone = skcms_MV_mul(&xyz_to_lms, &wXYZD50);
+    skcms_Vector3 srcCone = mv_mul(&xyz_to_lms, &wXYZ);
+    skcms_Vector3 dstCone = mv_mul(&xyz_to_lms, &wXYZD50);
 
     skcms_Matrix3x3 DXtoD50 = {{
         { dstCone.vals[0] / srcCone.vals[0], 0, 0 },
@@ -1171,23 +1259,13 @@
     return m;
 }
 
-skcms_Vector3 skcms_MV_mul(const skcms_Matrix3x3* m, const skcms_Vector3* v) {
-    skcms_Vector3 dst = {{0,0,0}};
-    for (int row = 0; row < 3; ++row) {
-        dst.vals[row] = m->vals[row][0] * v->vals[0]
-                      + m->vals[row][1] * v->vals[1]
-                      + m->vals[row][2] * v->vals[2];
-    }
-    return dst;
-}
-
 #if defined(__clang__) || defined(__GNUC__)
     #define small_memcpy __builtin_memcpy
 #else
     #define small_memcpy memcpy
 #endif
 
-float log2f_(float x) {
+static float log2f_(float x) {
     // The first approximation of log2(x) is its exponent 'e', minus 127.
     int32_t bits;
     small_memcpy(&bits, &x, sizeof(bits));
@@ -1204,7 +1282,7 @@
               -   1.725879990f/(0.3520887068f + m));
 }
 
-float exp2f_(float x) {
+static float exp2f_(float x) {
     float fract = x - floorf_(x);
 
     float fbits = (1.0f * (1<<23)) * (x + 121.274057500f
@@ -1233,20 +1311,6 @@
                              : powf_(tf->a * x + tf->b, tf->g) + tf->e);
 }
 
-bool skcms_TransferFunction_isValid(const skcms_TransferFunction* tf) {
-    // Reject obviously malformed inputs
-    if (!isfinitef_(tf->a + tf->b + tf->c + tf->d + tf->e + tf->f + tf->g)) {
-        return false;
-    }
-
-    // All of these parameters should be non-negative
-    if (tf->a < 0 || tf->c < 0 || tf->d < 0 || tf->g < 0) {
-        return false;
-    }
-
-    return true;
-}
-
 // TODO: Adjust logic here? This still assumes that purely linear inputs will have D > 1, which
 // we never generate. It also emits inverted linear using the same formulation. Standardize on
 // G == 1 here, too?
@@ -1269,7 +1333,7 @@
     skcms_TransferFunction tf_inv = { 0, 0, 0, 0, 0, 0, 0 };
 
     // This rejects obviously malformed inputs, as well as decreasing functions
-    if (!skcms_TransferFunction_isValid(src)) {
+    if (!tf_is_valid(src)) {
         return false;
     }
 
@@ -1341,10 +1405,10 @@
 //
 // Our overall strategy is then:
 //    For a couple tolerances,
-//       - skcms_fit_linear(): fit c,d,f iteratively to as many points as our tolerance allows
+//       - fit_linear():    fit c,d,f iteratively to as many points as our tolerance allows
 //       - invert c,d,f
-//       - fit_nonlinear():    fit g,a,b using Gauss-Newton given those inverted c,d,f
-//                             (and by constraint, inverted e) to the inverse of the table.
+//       - fit_nonlinear(): fit g,a,b using Gauss-Newton given those inverted c,d,f
+//                          (and by constraint, inverted e) to the inverse of the table.
 //    Return the parameters with least maximum error.
 //
 // To run Gauss-Newton to find g,a,b, we'll also need the gradient of the residuals
@@ -1367,7 +1431,7 @@
                           const skcms_TransferFunction* tf,
                           const float P[3],
                           float dfdP[3]) {
-    const float y = skcms_eval_curve(curve, x);
+    const float y = eval_curve(curve, x);
 
     const float g = P[0],  a = P[1],  b = P[2],
                 c = tf->c, d = tf->d, f = tf->f;
@@ -1391,50 +1455,6 @@
     return x - f_inv;
 }
 
-int skcms_fit_linear(const skcms_Curve* curve, int N, float tol, float* c, float* d, float* f) {
-    assert(N > 1);
-    // We iteratively fit the first points to the TF's linear piece.
-    // We want the cx + f line to pass through the first and last points we fit exactly.
-    //
-    // As we walk along the points we find the minimum and maximum slope of the line before the
-    // error would exceed our tolerance.  We stop when the range [slope_min, slope_max] becomes
-    // emtpy, when we definitely can't add any more points.
-    //
-    // Some points' error intervals may intersect the running interval but not lie fully
-    // within it.  So we keep track of the last point we saw that is a valid end point candidate,
-    // and once the search is done, back up to build the line through *that* point.
-    const float dx = 1.0f / (N - 1);
-
-    int lin_points = 1;
-    *f = skcms_eval_curve(curve, 0);
-
-    float slope_min = -INFINITY_;
-    float slope_max = +INFINITY_;
-    for (int i = 1; i < N; ++i) {
-        float x = i * dx;
-        float y = skcms_eval_curve(curve, x);
-
-        float slope_max_i = (y + tol - *f) / x,
-              slope_min_i = (y - tol - *f) / x;
-        if (slope_max_i < slope_min || slope_max < slope_min_i) {
-            // Slope intervals would no longer overlap.
-            break;
-        }
-        slope_max = fminf_(slope_max, slope_max_i);
-        slope_min = fmaxf_(slope_min, slope_min_i);
-
-        float cur_slope = (y - *f) / x;
-        if (slope_min <= cur_slope && cur_slope <= slope_max) {
-            lin_points = i + 1;
-            *c = cur_slope;
-        }
-    }
-
-    // Set D to the last point that met our tolerance.
-    *d = (lin_points - 1) * dx;
-    return lin_points;
-}
-
 static bool gauss_newton_step(const skcms_Curve* curve,
                               const skcms_TransferFunction* tf,
                               float P[3],
@@ -1508,7 +1528,7 @@
     }
 
     // 4) multiply inverse lhs by rhs
-    skcms_Vector3 dP = skcms_MV_mul(&lhs_inv, &rhs);
+    skcms_Vector3 dP = mv_mul(&lhs_inv, &rhs);
     P[0] += dP.vals[0];
     P[1] += dP.vals[1];
     P[2] += dP.vals[2];
@@ -1584,7 +1604,7 @@
     for (int t = 0; t < ARRAY_COUNT(kTolerances); t++) {
         skcms_TransferFunction tf,
                                tf_inv;
-        int L = skcms_fit_linear(curve, N, kTolerances[t], &tf.c, &tf.d, &tf.f);
+        int L = fit_linear(curve, N, kTolerances[t], &tf.c, &tf.d, &tf.f);
 
         if (L == N) {
             // If the entire data set was linear, move the coefficients to the nonlinear portion
@@ -1596,17 +1616,17 @@
         } else if (L == N - 1) {
             // Degenerate case with only two points in the nonlinear segment. Solve directly.
             tf.g = 1;
-            tf.a = (skcms_eval_curve(curve, (N-1)*dx) -
-                    skcms_eval_curve(curve, (N-2)*dx))
+            tf.a = (eval_curve(curve, (N-1)*dx) -
+                    eval_curve(curve, (N-2)*dx))
                  / dx;
-            tf.b = skcms_eval_curve(curve, (N-2)*dx)
+            tf.b = eval_curve(curve, (N-2)*dx)
                  - tf.a * (N-2)*dx;
             tf.e = 0;
         } else {
             // Start by guessing a gamma-only curve through the midpoint.
             int mid = (L + N) / 2;
             float mid_x = mid / (N - 1.0f);
-            float mid_y = skcms_eval_curve(curve, mid_x);
+            float mid_y = eval_curve(curve, mid_x);
             tf.g = log2f_(mid_y) / log2f_(mid_x);;
             tf.a = 1;
             tf.b = 0;
@@ -1636,7 +1656,7 @@
             continue;
         }
 
-        float err = skcms_MaxRoundtripError(curve, &tf_inv);
+        float err = max_roundtrip_error(curve, &tf_inv);
         if (*max_error > err) {
             *max_error = err;
             *approx    = tf;
@@ -1645,6 +1665,70 @@
     return isfinitef_(*max_error);
 }
 
+// ~~~~ Impl. of skcms_Transform() ~~~~
+
+typedef enum {
+    Op_noop,
+
+    Op_load_a8,
+    Op_load_g8,
+    Op_load_4444,
+    Op_load_565,
+    Op_load_888,
+    Op_load_8888,
+    Op_load_1010102,
+    Op_load_161616,
+    Op_load_16161616,
+    Op_load_hhh,
+    Op_load_hhhh,
+    Op_load_fff,
+    Op_load_ffff,
+
+    Op_swap_rb,
+    Op_clamp,
+    Op_invert,
+    Op_force_opaque,
+    Op_premul,
+    Op_unpremul,
+    Op_matrix_3x3,
+    Op_matrix_3x4,
+    Op_lab_to_xyz,
+
+    Op_tf_r,
+    Op_tf_g,
+    Op_tf_b,
+    Op_tf_a,
+
+    Op_table_8_r,
+    Op_table_8_g,
+    Op_table_8_b,
+    Op_table_8_a,
+
+    Op_table_16_r,
+    Op_table_16_g,
+    Op_table_16_b,
+    Op_table_16_a,
+
+    Op_clut_3D_8,
+    Op_clut_3D_16,
+    Op_clut_4D_8,
+    Op_clut_4D_16,
+
+    Op_store_a8,
+    Op_store_g8,
+    Op_store_4444,
+    Op_store_565,
+    Op_store_888,
+    Op_store_8888,
+    Op_store_1010102,
+    Op_store_161616,
+    Op_store_16161616,
+    Op_store_hhh,
+    Op_store_hhhh,
+    Op_store_fff,
+    Op_store_ffff,
+} Op;
+
 // Without this wasm would try to use the N=4 128-bit vector code path,
 // which while ideal, causes tons of compiler problems.  This would be
 // a good thing to revisit as emcc matures (currently 1.38.5).
@@ -1654,63 +1738,6 @@
     #endif
 #endif
 
-extern bool g_skcms_dump_profile;
-bool g_skcms_dump_profile = false;
-
-#if !defined(NDEBUG) && defined(__clang__)
-    // Basic profiling tools to time each Op.  Not at all thread safe.
-
-    #include <stdio.h>
-    #include <stdlib.h>
-
-    #if defined(__arm__) || defined(__aarch64__)
-        #include <time.h>
-        static const char* now_units = "ticks";
-        static uint64_t now() { return (uint64_t)clock(); }
-    #else
-        static const char* now_units = "cycles";
-        static uint64_t now() { return __builtin_readcyclecounter(); }
-    #endif
-
-    #define M(op) +1
-    static uint64_t counts[FOREACH_Op(M)];
-    #undef M
-
-    static void profile_dump_stats() {
-    #define M(op) #op,
-        static const char* names[] = { FOREACH_Op(M) };
-    #undef M
-        for (int i = 0; i < ARRAY_COUNT(counts); i++) {
-            if (counts[i]) {
-                fprintf(stderr, "%16s: %12llu %s\n",
-                        names[i], (unsigned long long)counts[i], now_units);
-            }
-        }
-    }
-
-    static inline Op profile_next_op(Op op) {
-        if (__builtin_expect(g_skcms_dump_profile, false)) {
-            static uint64_t start    = 0;
-            static uint64_t* current = NULL;
-
-            if (!current) {
-                atexit(profile_dump_stats);
-            } else {
-                *current += now() - start;
-            }
-
-            current = &counts[op];
-            start   = now();
-        }
-        return op;
-    }
-#else
-    static inline Op profile_next_op(Op op) {
-        (void)g_skcms_dump_profile;
-        return op;
-    }
-#endif
-
 #if defined(__clang__)
     typedef float    __attribute__((ext_vector_type(4)))   Fx4;
     typedef int32_t  __attribute__((ext_vector_type(4))) I32x4;
@@ -2309,7 +2336,7 @@
 
         float err = 0;
         for (int j = 0; j < 3; ++j) {
-            err = fmaxf_(err, skcms_MaxRoundtripError(&profile->trc[j], &inv));
+            err = fmaxf_(err, max_roundtrip_error(&profile->trc[j], &inv));
         }
         if (min_max_error > err) {
             min_max_error = err;
diff --git a/skcms_internal.h b/skcms_internal.h
index 97fc8de..d8fe695 100644
--- a/skcms_internal.h
+++ b/skcms_internal.h
@@ -19,38 +19,13 @@
 #endif
 
 // ~~~~ General Helper Macros ~~~~
-
-    // sizeof(x) will return size_t, which is 32-bit on some machines and 64-bit on others.
-    // We have better testing on 64-bit machines, so force 32-bit machines to behave like 64-bit.
-    #define SAFE_SIZEOF(x) ((uint64_t)sizeof(x))
-
-    // Please do not use sizeof() directly, and size_t only when required.
-    // (We have no way of enforcing these requests...)
-
-    #define ARRAY_COUNT(arr) (int)(SAFE_SIZEOF((arr)) / SAFE_SIZEOF(*(arr)))
-
-
-// ~~~~ skcms_Curve ~~~~
-
-    // Evaluate an skcms_Curve at x.
-    float skcms_eval_curve(const skcms_Curve*, float x);
-    float skcms_MaxRoundtripError(const skcms_Curve*, const skcms_TransferFunction*);
-
+    #define ARRAY_COUNT(arr) (int)(sizeof((arr)) / sizeof(*(arr)))
 
 // ~~~~ skcms_TransferFunction ~~~~
-    bool skcms_TransferFunction_isValid(const skcms_TransferFunction*);
-
-    float skcms_TransferFunction_eval(const skcms_TransferFunction*, float);
-
-    bool skcms_TransferFunction_invert(const skcms_TransferFunction*, skcms_TransferFunction*);
-
-    // Fit c,d,f parameters of an skcms_TransferFunction to the first 2 ≤ L ≤ N
-    // evenly-spaced points on an skcms_Curve within a given tolerance, returning L.
-    int skcms_fit_linear(const skcms_Curve*, int N, float tol, float* c, float* d, float* f);
-
+    float skcms_TransferFunction_eval  (const skcms_TransferFunction*, float);
+    bool  skcms_TransferFunction_invert(const skcms_TransferFunction*, skcms_TransferFunction*);
 
 // ~~~~ skcms_ICCProfile ~~~~
-
     bool skcms_GetCHAD(const skcms_ICCProfile* profile, skcms_Matrix3x3* m);
 
     // 252 of a random shuffle of all possible bytes.
@@ -58,105 +33,19 @@
     // Used for ICC profile equivalence testing.
     extern const uint8_t skcms_252_random_bytes[252];
 
-
 // ~~~~ Linear Algebra ~~~~
-
-    typedef struct { float vals[3]; } skcms_Vector3;
-
     // It is _not_ safe to alias the pointers to invert in-place.
     bool skcms_Matrix3x3_invert(const skcms_Matrix3x3*, skcms_Matrix3x3*);
     skcms_Matrix3x3 skcms_Matrix3x3_concat(const skcms_Matrix3x3* A, const skcms_Matrix3x3* B);
 
-    skcms_Vector3 skcms_MV_mul(const skcms_Matrix3x3*, const skcms_Vector3*);
-
-
 // ~~~~ Portable Math ~~~~
-
-    static const union {
-        uint32_t bits;
-        float    f;
-    } inf_ = { 0x7f800000 };
-
-    #define INFINITY_ inf_.f
-
     static inline float floorf_(float x) {
         float roundtrip = (float)((int)x);
         return roundtrip > x ? roundtrip - 1 : roundtrip;
     }
-
-    static inline float fmaxf_(float x, float y) { return x > y ? x : y; }
-    static inline float fminf_(float x, float y) { return x < y ? x : y; }
     static inline float fabsf_(float x) { return x < 0 ? -x : x; }
-
-    float log2f_(float);
-    float exp2f_(float);
     float powf_(float, float);
 
-    static inline bool isfinitef_(float x) { return 0 == x*0; }
-
-
-// ~~~~ Transform ~~~~
-
-    #define FOREACH_Op(M) \
-        M(noop)           \
-        M(load_a8)        \
-        M(load_g8)        \
-        M(load_4444)      \
-        M(load_565)       \
-        M(load_888)       \
-        M(load_8888)      \
-        M(load_1010102)   \
-        M(load_161616)    \
-        M(load_16161616)  \
-        M(load_hhh)       \
-        M(load_hhhh)      \
-        M(load_fff)       \
-        M(load_ffff)      \
-        M(swap_rb)        \
-        M(clamp)          \
-        M(invert)         \
-        M(force_opaque)   \
-        M(premul)         \
-        M(unpremul)       \
-        M(matrix_3x3)     \
-        M(matrix_3x4)     \
-        M(lab_to_xyz)     \
-        M(tf_r)           \
-        M(tf_g)           \
-        M(tf_b)           \
-        M(tf_a)           \
-        M(table_8_r)      \
-        M(table_8_g)      \
-        M(table_8_b)      \
-        M(table_8_a)      \
-        M(table_16_r)     \
-        M(table_16_g)     \
-        M(table_16_b)     \
-        M(table_16_a)     \
-        M(clut_3D_8)      \
-        M(clut_3D_16)     \
-        M(clut_4D_8)      \
-        M(clut_4D_16)     \
-        M(store_a8)       \
-        M(store_g8)       \
-        M(store_4444)     \
-        M(store_565)      \
-        M(store_888)      \
-        M(store_8888)     \
-        M(store_1010102)  \
-        M(store_161616)   \
-        M(store_16161616) \
-        M(store_hhh)      \
-        M(store_hhhh)     \
-        M(store_fff)      \
-        M(store_ffff)
-
-    typedef enum {
-        #define M(op) Op_##op,
-        FOREACH_Op(M)
-        #undef M
-    } Op;
-
 #if defined(__cpluscplus)
 }  // extern "C"
 #endif
diff --git a/src/Transform_inl.h b/src/Transform_inl.h
index 34dcbbf..a8f3c8a 100644
--- a/src/Transform_inl.h
+++ b/src/Transform_inl.h
@@ -5,11 +5,9 @@
  * found in the LICENSE file.
  */
 
-// Intentionally NO #pragma once
+// Intentionally NO #pragma once... included multiple times.
 
-#include "../skcms_internal.h"
-
-// This file is included from src/Transform.c, with some values and types pre-defined:
+// This file is included from skcms.c with some values and types pre-defined:
 //    N:    depth of all vectors, 1,4,8, or 16
 //
 //    F:    a vector of N float
@@ -573,7 +571,7 @@
                          const char* src, char* dst, int i) {
     F r = F0, g = F0, b = F0, a = F0;
     while (true) {
-        switch (profile_next_op(*ops++)) {
+        switch (*ops++) {
             case Op_noop: break;
 
             case Op_load_a8:{
diff --git a/tests.c b/tests.c
index 28f7802..09669f7 100644
--- a/tests.c
+++ b/tests.c
@@ -1086,26 +1086,6 @@
     expect(skcms_ApproximatelyEqualProfiles(&p, &srgb));
 }
 
-static void test_isfinitef_() {
-    uint32_t denorm_bits = 0x00000001,
-                nan_bits = 0xffffffff;
-    float denorm,
-             nan;
-    memcpy(&denorm, &denorm_bits, 4);
-    memcpy(&   nan, &   nan_bits, 4);
-
-    expect( isfinitef_(+0.0f));
-    expect( isfinitef_(-0.0f));
-    expect( isfinitef_(+1.0f));
-    expect( isfinitef_(-1.0f));
-    expect( isfinitef_(+denorm));
-    expect( isfinitef_(-denorm));
-    expect(!isfinitef_(+INFINITY_));
-    expect(!isfinitef_(-INFINITY_));
-    expect(!isfinitef_(+nan));
-    expect(!isfinitef_(-nan));
-}
-
 int main(int argc, char** argv) {
     bool regenTestData = false;
     for (int i = 1; i < argc; ++i) {
@@ -1135,7 +1115,6 @@
     test_MakeUsableAsDestinationAdobe();
     test_PrimariesToXYZ();
     test_Programmatic_sRGB();
-    test_isfinitef_();
 #if 0
     test_CLUT();
 #endif