[gs-commits] ghostpdl branch, master, updated. jbig2dec-0.14-1655-gbc48c29

[email protected] (Robin Watts)
Newsgroups gmane.comp.printing.ghostscript.cvs
Message-ID <[email protected]>
The ghostpdl branch, master has been updated
       via  bc48c29c5e86e6c528e23140c71ecfb58588333f (commit)
       via  63e1fd40674a4f89f6593098cf100382061753e5 (commit)
       via  1cc72912138544dcf00ed0dbc77ceaf47de04e91 (commit)
       via  3f46434c0fe3707f53a825f39fa1bab8c0875c03 (commit)
      from  b5e5ed8620f348e0fa619171d6f05a966a4bcf83 (commit)

----------------------------------------------------------------------
commit bc48c29c5e86e6c528e23140c71ecfb58588333f
Author: Robin Watts <[email protected]>
Date:   Mon Sep 9 14:19:33 2019 +0100

    Optimise Eval{5,6,7,8}Inputs{,Float}.
    
    Only use 1 Temporary array, and avoid needless work in the
    0xFFFF cases.

diff --git a/lcms2mt/src/cmsintrp.c b/lcms2mt/src/cmsintrp.c
index 3585e4f..b6846f6 100644
--- a/lcms2mt/src/cmsintrp.c
+++ b/lcms2mt/src/cmsintrp.c
@@ -1180,41 +1180,27 @@ void Eval5Inputs(cmsContext ContextID, register const cmsUInt16Number Input[],
                  register cmsUInt16Number Output[],
                  register const cmsInterpParams* p16)
 {
-       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
-       cmsS15Fixed16Number fk;
-       cmsS15Fixed16Number k0, rk;
-       int K0, K1;
-       const cmsUInt16Number* T;
-       cmsUInt32Number i;
-       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
-       cmsInterpParams p1;
+    cmsS15Fixed16Number fk;
+    cmsUInt32Number i, n;
+    cmsUInt16Number Tmp[MAX_STAGE_CHANNELS];
+    cmsInterpParams p1 = *p16;
 
+    memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
+    fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
+    p1.Table = ((cmsUInt16Number*)p16 -> Table) + p16 -> opta[4] * FIXED_TO_INT(fk);
 
-       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
-       k0 = FIXED_TO_INT(fk);
-       rk = FIXED_REST_TO_INT(fk);
+    Eval4Inputs(ContextID, Input + 1, Output, &p1);
 
-       K0 = p16 -> opta[4] * k0;
-       K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
+    if (Input[0] == 0xFFFFU)
+        return;
 
-       p1 = *p16;
-       memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
-
-       T = LutTable + K0;
-       p1.Table = T;
-
-       Eval4Inputs(ContextID, Input + 1, Tmp1, &p1);
-
-       T = LutTable + K1;
-       p1.Table = T;
-
-       Eval4Inputs(ContextID, Input + 1, Tmp2, &p1);
-
-       for (i=0; i < p16 -> nOutputs; i++) {
-
-              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
-       }
+    p1.Table = ((cmsUInt16Number*)p1.Table) + p16 -> opta[4];
+    Eval4Inputs(ContextID, Input + 1, Tmp, &p1);
 
+    fk = FIXED_REST_TO_INT(fk);
+    n = p16 -> nOutputs;
+    for (i=0; i < n; i++)
+        Output[i] = LinearInterp(fk, Output[i], Tmp[i]);
 }
 
 
@@ -1223,42 +1209,36 @@ void Eval5InputsFloat(cmsContext ContextID, const cmsFloat32Number Input[],
                       cmsFloat32Number Output[],
                       const cmsInterpParams* p)
 {
-       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
-       cmsFloat32Number rest;
-       cmsFloat32Number pk;
-       int k0, K0, K1;
-       const cmsFloat32Number* T;
-       cmsUInt32Number i;
-       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
-       cmsInterpParams p1;
+    cmsFloat32Number rest;
+    cmsFloat32Number pk;
+    int k0;
+    cmsUInt32Number i, n;
+    cmsFloat32Number Tmp[MAX_STAGE_CHANNELS];
+    cmsInterpParams p1 = *p;
+    cmsFloat32Number i0 = fclamp(Input[0]);
 
-       pk = fclamp(Input[0]) * p->Domain[0];
-       k0 = _cmsQuickFloor(pk);
-       rest = pk - (cmsFloat32Number) k0;
+    pk = i0 * p->Domain[0];
+    k0 = _cmsQuickFloor(pk);
+    rest = pk - (cmsFloat32Number) k0;
 
-       K0 = p -> opta[4] * k0;
-       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[4]);
+    memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
+    p1.Table = ((cmsFloat32Number*) p -> Table) + p -> opta[4] * k0;
 
-       p1 = *p;
-       memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
+    Eval4InputsFloat(ContextID, Input + 1,  Output, &p1);
 
-       T = LutTable + K0;
-       p1.Table = T;
+    if (i0 == 1.0)
+        return;
 
-       Eval4InputsFloat(ContextID, Input + 1,  Tmp1, &p1);
+    p1.Table = ((cmsFloat32Number*) p1.Table) + p->opta[4];
+    Eval4InputsFloat(ContextID, Input + 1,  Tmp, &p1);
 
-       T = LutTable + K1;
-       p1.Table = T;
+    n = p -> nOutputs;
+    for (i=0; i < n; i++) {
+        cmsFloat32Number y0 = Output[i];
+        cmsFloat32Number y1 = Tmp[i];
 
-       Eval4InputsFloat(ContextID, Input + 1,  Tmp2, &p1);
-
-       for (i=0; i < p -> nOutputs; i++) {
-
-              cmsFloat32Number y0 = Tmp1[i];
-              cmsFloat32Number y1 = Tmp2[i];
-
-              Output[i] = y0 + (y1 - y0) * rest;
-       }
+        Output[i] = y0 + (y1 - y0) * rest;
+    }
 }
 
 
@@ -1268,40 +1248,27 @@ void Eval6Inputs(cmsContext ContextID, register const cmsUInt16Number Input[],
                  register cmsUInt16Number Output[],
                  register const cmsInterpParams* p16)
 {
-       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
-       cmsS15Fixed16Number fk;
-       cmsS15Fixed16Number k0, rk;
-       int K0, K1;
-       const cmsUInt16Number* T;
-       cmsUInt32Number i;
-       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
-       cmsInterpParams p1;
+    cmsS15Fixed16Number fk;
+    cmsUInt32Number i, n;
+    cmsUInt16Number Tmp[MAX_STAGE_CHANNELS];
+    cmsInterpParams p1 = *p16;
 
-       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
-       k0 = FIXED_TO_INT(fk);
-       rk = FIXED_REST_TO_INT(fk);
+    memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
+    fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
+    p1.Table = ((cmsUInt16Number*)p16 -> Table) + p16 -> opta[5] * FIXED_TO_INT(fk);
 
-       K0 = p16 -> opta[5] * k0;
-       K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
+    Eval5Inputs(ContextID, Input + 1, Output, &p1);
 
-       p1 = *p16;
-       memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
+    if (Input[0] == 0xFFFFU)
+        return;
 
-       T = LutTable + K0;
-       p1.Table = T;
-
-       Eval5Inputs(ContextID, Input + 1, Tmp1, &p1);
-
-       T = LutTable + K1;
-       p1.Table = T;
-
-       Eval5Inputs(ContextID, Input + 1, Tmp2, &p1);
-
-       for (i=0; i < p16 -> nOutputs; i++) {
-
-              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
-       }
+    p1.Table = ((cmsUInt16Number*)p1.Table) + p16 -> opta[5];
+    Eval5Inputs(ContextID, Input + 1, Tmp, &p1);
 
+    fk = FIXED_REST_TO_INT(fk);
+    n = p16 -> nOutputs;
+    for (i=0; i < n; i++)
+        Output[i] = LinearInterp(fk, Output[i], Tmp[i]);
 }
 
 
@@ -1310,42 +1277,36 @@ void Eval6InputsFloat(cmsContext ContextID, const cmsFloat32Number Input[],
                       cmsFloat32Number Output[],
                       const cmsInterpParams* p)
 {
-       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
-       cmsFloat32Number rest;
-       cmsFloat32Number pk;
-       int k0, K0, K1;
-       const cmsFloat32Number* T;
-       cmsUInt32Number i;
-       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
-       cmsInterpParams p1;
+    cmsFloat32Number rest;
+    cmsFloat32Number pk;
+    int k0;
+    cmsUInt32Number i, n;
+    cmsFloat32Number Tmp[MAX_STAGE_CHANNELS];
+    cmsInterpParams p1 = *p;
+    cmsFloat32Number i0 = fclamp(Input[0]);
 
-       pk = fclamp(Input[0]) * p->Domain[0];
-       k0 = _cmsQuickFloor(pk);
-       rest = pk - (cmsFloat32Number) k0;
+    pk = i0 * p->Domain[0];
+    k0 = _cmsQuickFloor(pk);
+    rest = pk - (cmsFloat32Number) k0;
 
-       K0 = p -> opta[5] * k0;
-       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[5]);
+    memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
+    p1.Table = ((cmsFloat32Number*) p -> Table) + p -> opta[5] * k0;
 
-       p1 = *p;
-       memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
+    Eval5InputsFloat(ContextID, Input + 1,  Output, &p1);
 
-       T = LutTable + K0;
-       p1.Table = T;
+    if (i0 == 1.0)
+        return;
 
-       Eval5InputsFloat(ContextID, Input + 1,  Tmp1, &p1);
+    p1.Table = ((cmsFloat32Number*) p1.Table) + p->opta[5];
+    Eval5InputsFloat(ContextID, Input + 1,  Tmp, &p1);
 
-       T = LutTable + K1;
-       p1.Table = T;
+    n = p -> nOutputs;
+    for (i=0; i < n; i++) {
+        cmsFloat32Number y0 = Output[i];
+        cmsFloat32Number y1 = Tmp[i];
 
-       Eval5InputsFloat(ContextID, Input + 1,  Tmp2, &p1);
-
-       for (i=0; i < p -> nOutputs; i++) {
-
-              cmsFloat32Number y0 = Tmp1[i];
-              cmsFloat32Number y1 = Tmp2[i];
-
-              Output[i] = y0 + (y1 - y0) * rest;
-       }
+        Output[i] = y0 + (y1 - y0) * rest;
+    }
 }
 
 
@@ -1354,39 +1315,27 @@ void Eval7Inputs(cmsContext ContextID, register const cmsUInt16Number Input[],
                  register cmsUInt16Number Output[],
                  register const cmsInterpParams* p16)
 {
-       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
-       cmsS15Fixed16Number fk;
-       cmsS15Fixed16Number k0, rk;
-       int K0, K1;
-       const cmsUInt16Number* T;
-       cmsUInt32Number i;
-       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
-       cmsInterpParams p1;
+    cmsS15Fixed16Number fk;
+    cmsUInt32Number i, n;
+    cmsUInt16Number Tmp[MAX_STAGE_CHANNELS];
+    cmsInterpParams p1 = *p16;
 
+    memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
+    fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
+    p1.Table = ((cmsUInt16Number*)p16 -> Table) + p16 -> opta[6] * FIXED_TO_INT(fk);
 
-       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
-       k0 = FIXED_TO_INT(fk);
-       rk = FIXED_REST_TO_INT(fk);
+    Eval6Inputs(ContextID, Input + 1, Output, &p1);
 
-       K0 = p16 -> opta[6] * k0;
-       K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
+    if (Input[0] == 0xFFFFU)
+        return;
 
-       p1 = *p16;
-       memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
+    p1.Table = ((cmsUInt16Number*)p1.Table) + p16 -> opta[6];
+    Eval6Inputs(ContextID, Input + 1, Tmp, &p1);
 
-       T = LutTable + K0;
-       p1.Table = T;
-
-       Eval6Inputs(ContextID, Input + 1, Tmp1, &p1);
-
-       T = LutTable + K1;
-       p1.Table = T;
-
-       Eval6Inputs(ContextID, Input + 1, Tmp2, &p1);
-
-       for (i=0; i < p16 -> nOutputs; i++) {
-              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
-       }
+    fk = FIXED_REST_TO_INT(fk);
+    n = p16 -> nOutputs;
+    for (i=0; i < n; i++)
+        Output[i] = LinearInterp(fk, Output[i], Tmp[i]);
 }
 
 
@@ -1395,44 +1344,36 @@ void Eval7InputsFloat(cmsContext ContextID, const cmsFloat32Number Input[],
                       cmsFloat32Number Output[],
                       const cmsInterpParams* p)
 {
-       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
-       cmsFloat32Number rest;
-       cmsFloat32Number pk;
-       int k0, K0, K1;
-       const cmsFloat32Number* T;
-       cmsUInt32Number i;
-       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
-       cmsInterpParams p1;
+    cmsFloat32Number rest;
+    cmsFloat32Number pk;
+    int k0;
+    cmsUInt32Number i, n;
+    cmsFloat32Number Tmp[MAX_STAGE_CHANNELS];
+    cmsInterpParams p1 = *p;
+    cmsFloat32Number i0 = fclamp(Input[0]);
 
-       pk = fclamp(Input[0]) * p->Domain[0];
-       k0 = _cmsQuickFloor(pk);
-       rest = pk - (cmsFloat32Number) k0;
+    pk = i0 * p->Domain[0];
+    k0 = _cmsQuickFloor(pk);
+    rest = pk - (cmsFloat32Number) k0;
 
-       K0 = p -> opta[6] * k0;
-       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[6]);
+    memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
+    p1.Table = ((cmsFloat32Number*) p -> Table) + p -> opta[6] * k0;
 
-       p1 = *p;
-       memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
+    Eval6InputsFloat(ContextID, Input + 1,  Output, &p1);
 
-       T = LutTable + K0;
-       p1.Table = T;
+    if (i0 == 1.0)
+        return;
 
-       Eval6InputsFloat(ContextID, Input + 1,  Tmp1, &p1);
+    p1.Table = ((cmsFloat32Number*) p1.Table) + p->opta[6];
+    Eval6InputsFloat(ContextID, Input + 1,  Tmp, &p1);
 
-       T = LutTable + K1;
-       p1.Table = T;
+    n = p -> nOutputs;
+    for (i=0; i < n; i++) {
+        cmsFloat32Number y0 = Output[i];
+        cmsFloat32Number y1 = Tmp[i];
 
-       Eval6InputsFloat(ContextID, Input + 1,  Tmp2, &p1);
-
-
-       for (i=0; i < p -> nOutputs; i++) {
-
-              cmsFloat32Number y0 = Tmp1[i];
-              cmsFloat32Number y1 = Tmp2[i];
-
-              Output[i] = y0 + (y1 - y0) * rest;
-
-       }
+        Output[i] = y0 + (y1 - y0) * rest;
+    }
 }
 
 static CMS_NO_SANITIZE
@@ -1440,37 +1381,27 @@ void Eval8Inputs(cmsContext ContextID, register const cmsUInt16Number Input[],
                  register cmsUInt16Number Output[],
                  register const cmsInterpParams* p16)
 {
-       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
-       cmsS15Fixed16Number fk;
-       cmsS15Fixed16Number k0, rk;
-       int K0, K1;
-       const cmsUInt16Number* T;
-       cmsUInt32Number i;
-       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
-       cmsInterpParams p1;
+    cmsS15Fixed16Number fk;
+    cmsUInt32Number i, n;
+    cmsUInt16Number Tmp[MAX_STAGE_CHANNELS];
+    cmsInterpParams p1 = *p16;
 
-       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
-       k0 = FIXED_TO_INT(fk);
-       rk = FIXED_REST_TO_INT(fk);
+    memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
+    fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
+    p1.Table = ((cmsUInt16Number*)p16 -> Table) + p16 -> opta[7] * FIXED_TO_INT(fk);
 
-       K0 = p16 -> opta[7] * k0;
-       K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
+    Eval7Inputs(ContextID, Input + 1, Output, &p1);
 
-       p1 = *p16;
-       memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
+    if (Input[0] == 0xFFFFU)
+        return;
 
-       T = LutTable + K0;
-       p1.Table = T;
+    p1.Table = ((cmsUInt16Number*)p1.Table) + p16 -> opta[7];
+    Eval7Inputs(ContextID, Input + 1, Tmp, &p1);
 
-       Eval7Inputs(ContextID, Input + 1, Tmp1, &p1);
-
-       T = LutTable + K1;
-       p1.Table = T;
-       Eval7Inputs(ContextID, Input + 1, Tmp2, &p1);
-
-       for (i=0; i < p16 -> nOutputs; i++) {
-              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
-       }
+    fk = FIXED_REST_TO_INT(fk);
+    n = p16 -> nOutputs;
+    for (i=0; i < n; i++)
+        Output[i] = LinearInterp(fk, Output[i], Tmp[i]);
 }
 
 
@@ -1480,43 +1411,36 @@ void Eval8InputsFloat(cmsContext ContextID, const cmsFloat32Number Input[],
                       cmsFloat32Number Output[],
                       const cmsInterpParams* p)
 {
-       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
-       cmsFloat32Number rest;
-       cmsFloat32Number pk;
-       int k0, K0, K1;
-       const cmsFloat32Number* T;
-       cmsUInt32Number i;
-       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
-       cmsInterpParams p1;
+    cmsFloat32Number rest;
+    cmsFloat32Number pk;
+    int k0;
+    cmsUInt32Number i, n;
+    cmsFloat32Number Tmp[MAX_STAGE_CHANNELS];
+    cmsInterpParams p1 = *p;
+    cmsFloat32Number i0 = fclamp(Input[0]);
 
-       pk = fclamp(Input[0]) * p->Domain[0];
-       k0 = _cmsQuickFloor(pk);
-       rest = pk - (cmsFloat32Number) k0;
+    pk = i0 * p->Domain[0];
+    k0 = _cmsQuickFloor(pk);
+    rest = pk - (cmsFloat32Number) k0;
 
-       K0 = p -> opta[7] * k0;
-       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[7]);
+    memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
+    p1.Table = ((cmsFloat32Number*) p -> Table) + p -> opta[7] * k0;
 
-       p1 = *p;
-       memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
+    Eval7InputsFloat(ContextID, Input + 1,  Output, &p1);
 
-       T = LutTable + K0;
-       p1.Table = T;
+    if (i0 == 1.0)
+        return;
 
-       Eval7InputsFloat(ContextID, Input + 1,  Tmp1, &p1);
+    p1.Table = ((cmsFloat32Number*) p1.Table) + p->opta[7];
+    Eval7InputsFloat(ContextID, Input + 1,  Tmp, &p1);
 
-       T = LutTable + K1;
-       p1.Table = T;
+    n = p -> nOutputs;
+    for (i=0; i < n; i++) {
+        cmsFloat32Number y0 = Output[i];
+        cmsFloat32Number y1 = Tmp[i];
 
-       Eval7InputsFloat(ContextID, Input + 1,  Tmp2, &p1);
-
-
-       for (i=0; i < p -> nOutputs; i++) {
-
-              cmsFloat32Number y0 = Tmp1[i];
-              cmsFloat32Number y1 = Tmp2[i];
-
-              Output[i] = y0 + (y1 - y0) * rest;
-       }
+        Output[i] = y0 + (y1 - y0) * rest;
+    }
 }
 
 // The default factory

----------------------------------------------------------------------
commit 63e1fd40674a4f89f6593098cf100382061753e5
Author: Robin Watts <[email protected]>
Date:   Mon Sep 9 11:03:59 2019 +0100

    Tweak Eval4InputsFloat for speed.
    
    Move to the Pentachoronal Interpolation algorithm.

diff --git a/lcms2mt/src/cmsintrp.c b/lcms2mt/src/cmsintrp.c
index f4f22be..3585e4f 100644
--- a/lcms2mt/src/cmsintrp.c
+++ b/lcms2mt/src/cmsintrp.c
@@ -1061,69 +1061,81 @@ void Eval4InputsFloat(cmsContext ContextID, const cmsFloat32Number Input[],
     LutTable = (cmsFloat32Number*) p -> Table;
     LutTable += K0 + X0 + Y0 + Z0;
 
-    which = (ry > rx ?  1 : 0) +
-            (rz > rx ?  2 : 0) +
-            (rk > rx ?  4 : 0) +
-            (rz > ry ?  8 : 0) +
-            (rk > ry ? 16 : 0) +
-            (rk > rz ? 32 : 0);
-    /* This gives us 24 possible cases:
-     * which                        Tetrahedral corners
-     * 0x00  rx >= ry >= rz >= rk   (0,0,0,0) (1,0,0,0) (1,1,0,0) (1,1,1,0) (1,1,1,1)
-     * 0x01  ry >  rx >= rz >= rk   (0,0,0,0) (0,1,0,0) (1,1,0,0) (1,1,1,0) (1,1,1,1)
-     * 0x03  ry >= rz >  rx >= rk   (0,0,0,0) (0,1,0,0) (0,1,1,0) (1,1,1,0) (1,1,1,1)
-     * 0x07  ry >= rz >= rk >  rx   (0,0,0,0) (0,1,0,0) (0,1,1,0) (0,1,1,1) (1,1,1,1)
-     * 0x08  rx >= rz >  ry >= rk   (0,0,0,0) (1,0,0,0) (1,0,1,0) (1,1,1,0) (1,1,1,1)
-     * 0x0a  rz >  rx >= ry >= rk   (0,0,0,0) (0,0,1,0) (1,0,1,0) (1,1,1,0) (1,1,1,1)
-     * 0x0b  rz >  ry >  rx >= rk   (0,0,0,0) (0,0,1,0) (0,1,1,0) (1,1,1,0) (1,1,1,1)
-     * 0x0f  rz >  ry >= rk >  rx   (0,0,0,0) (0,0,1,0) (0,1,1,0) (0,1,1,1) (1,1,1,1)
-     * 0x18  rx >= rz >= rk >  ry   (0,0,0,0) (1,0,0,0) (1,0,1,0) (1,0,1,1) (1,1,1,1)
-     * 0x1a  rz >  rx >= rk >  ry   (0,0,0,0) (0,0,1,0) (1,0,1,0) (1,0,1,1) (1,1,1,1)
-     * 0x1e  rz >= rk >  rx >= ry   (0,0,0,0) (0,0,1,0) (0,0,1,1) (1,0,1,1) (1,1,1,1)
-     * 0x1f  rz >= rk >  ry >  rx   (0,0,0,0) (0,0,1,0) (0,0,1,1) (0,1,1,1) (1,1,1,1)
-     * 0x20  rx >= ry >= rk >  rz   (0,0,0,0) (1,0,0,0) (1,1,0,0) (1,1,0,1) (1,1,1,1)
-     * 0x21  ry >  rx >= rk >  rz   (0,0,0,0) (0,1,0,0) (1,1,0,0) (1,1,0,1) (1,1,1,1)
-     * 0x25  ry >= rk >  rx >= rz   (0,0,0,0) (0,1,0,0) (0,1,0,1) (1,1,0,1) (1,1,1,1)
-     * 0x27  ry >= rk >  rz >  rx   (0,0,0,0) (0,1,0,0) (0,1,0,1) (0,1,1,1) (1,1,1,1)
-     * 0x30  rx >= rk >  ry >= rz   (0,0,0,0) (1,0,0,0) (1,0,0,1) (1,1,0,1) (1,1,1,1)
-     * 0x34  rk >  rx >= ry >= rz   (0,0,0,0) (0,0,0,1) (1,0,0,1) (1,1,0,1) (1,1,1,1)
-     * 0x35  rk >  ry >  rx >= rz   (0,0,0,0) (0,0,0,1) (0,1,0,1) (1,1,0,1) (1,1,1,1)
-     * 0x37  rk >  ry >= rz >  rx   (0,0,0,0) (0,0,0,1) (0,1,0,1) (0,1,1,1) (1,1,1,1)
-     * 0x38  rx >= rk >  rz >  ry   (0,0,0,0) (1,0,0,0) (1,0,0,1) (1,0,1,1) (1,1,1,1)
-     * 0x3c  rk >  rx >= rz >  ry   (0,0,0,0) (0,0,0,1) (1,0,0,1) (1,0,1,1) (1,1,1,1)
-     * 0x3e  rk >  rz >  rx >= ry   (0,0,0,0) (0,0,0,1) (0,0,1,1) (1,0,1,1) (1,1,1,1)
-     * 0x3f  rk >  rz >  ry  > rx   (0,0,0,0) (0,0,0,1) (0,0,1,1) (0,1,1,1) (1,1,1,1)
-     */
+    /* We carefully choose the following tests, a) cos these
+     * work nicely in SSE (see CAL), and b) because, as well
+     * as the standard 24 pentachorons, we get some useful
+     * special cases. */
+    which = (rx > ry ?  1 : 0) +
+            (ry > rz ?  2 : 0) +
+            (rz > rk ?  4 : 0) +
+            (rk > rx ?  8 : 0) +
+            (rz > rx ? 16 : 0) +
+            (rk > ry ? 32 : 0);
 
     o4 = X1+Y1+Z1+K1;
     switch(which)
     {
-        default: /* Never happens, but stops the compiler complaining of uninitialised vars */
-        case 0x00: o1 = X1; o2 = Y1; o3 = Z1; m1 = rx; m2 = ry; m3 = rz; m4 = rk; break;
-        case 0x01: o1 = Y1; o2 = X1; o3 = Z1; m1 = ry; m2 = rx; m3 = rz; m4 = rk; break;
-        case 0x03: o1 = Y1; o2 = Z1; o3 = X1; m1 = ry; m2 = rz; m3 = rx; m4 = rk; break;
-        case 0x07: o1 = Y1; o2 = Z1; o3 = K1; m1 = ry; m2 = rz; m3 = rk; m4 = rx; break;
-        case 0x08: o1 = X1; o2 = Z1; o3 = Y1; m1 = rx; m2 = rz; m3 = ry; m4 = rk; break;
-        case 0x0a: o1 = Z1; o2 = X1; o3 = Y1; m1 = rz; m2 = rx; m3 = ry; m4 = rk; break;
-        case 0x0b: o1 = Z1; o2 = Y1; o3 = X1; m1 = rz; m2 = ry; m3 = rx; m4 = rk; break;
-        case 0x0f: o1 = Z1; o2 = Y1; o3 = K1; m1 = rz; m2 = ry; m3 = rk; m4 = rx; break;
-        case 0x18: o1 = X1; o2 = Z1; o3 = K1; m1 = rx; m2 = rz; m3 = rk; m4 = ry; break;
-        case 0x1a: o1 = Z1; o2 = X1; o3 = K1; m1 = rz; m2 = rx; m3 = rk; m4 = ry; break;
-        case 0x1e: o1 = Z1; o2 = K1; o3 = X1; m1 = rz; m2 = rk; m3 = rx; m4 = ry; break;
-        case 0x1f: o1 = Z1; o2 = K1; o3 = Y1; m1 = rz; m2 = rk; m3 = ry; m4 = rx; break;
-        case 0x20: o1 = X1; o2 = Y1; o3 = K1; m1 = rx; m2 = ry; m3 = rk; m4 = rz; break;
-        case 0x21: o1 = Y1; o2 = X1; o3 = K1; m1 = ry; m2 = rx; m3 = rk; m4 = rz; break;
-        case 0x25: o1 = Y1; o2 = K1; o3 = X1; m1 = ry; m2 = rk; m3 = rx; m4 = rz; break;
-        case 0x27: o1 = Y1; o2 = K1; o3 = Z1; m1 = ry; m2 = rk; m3 = rz; m4 = rx; break;
-        case 0x30: o1 = X1; o2 = K1; o3 = Y1; m1 = rx; m2 = rk; m3 = ry; m4 = rz; break;
-        case 0x34: o1 = K1; o2 = X1; o3 = Y1; m1 = rk; m2 = rx; m3 = ry; m4 = rz; break;
-        case 0x35: o1 = K1; o2 = Y1; o3 = X1; m1 = rk; m2 = ry; m3 = rx; m4 = rz; break;
-        case 0x37: o1 = K1; o2 = Y1; o3 = Z1; m1 = rk; m2 = ry; m3 = rz; m4 = rx; break;
-        case 0x38: o1 = X1; o2 = K1; o3 = Z1; m1 = rx; m2 = rk; m3 = rz; m4 = ry; break;
-        case 0x3c: o1 = K1; o2 = X1; o3 = Z1; m1 = rk; m2 = rx; m3 = rz; m4 = ry; break;
-        case 0x3e: o1 = K1; o2 = Z1; o3 = X1; m1 = rk; m2 = rz; m3 = rx; m4 = ry; break;
-        case 0x3f: o1 = K1; o2 = Z1; o3 = Y1; m1 = rk; m2 = rz; m3 = ry; m4 = rx; break;
+        default:    /* Never happens, but stops the compiler complaining of uninitialised vars */
+        case 0x00:  /* x == y == z == k - special case */
+            m1 = rx; goto one_lerp;
+        case 0x01:  /* x >  k == z == y - special case */
+            o1 = X1;       m1 = rx; m2 = ry; goto two_lerps;
+        case 0x18:  /* y == z == k >  x - special case */
+            o1 = Y1+Z1+K1; m1 = ry; m2 = rx; goto two_lerps;
+        case 0x04:  /* z == y == x >  k - special case */
+            o1 = X1+Y1+Z1; m1 = ry; m2 = rk; goto two_lerps;
+        case 0x28:  /* k >  z == y == x - special case */
+            o1 = K1;       m1 = rk; m2 = ry; goto two_lerps;
+        case 0x02:  /* y >= x >= k >= z */
+            o1 = Y1; o2 = X1; o3 = K1; m1 = ry; m2 = rx; m3 = rk; m4 = rz; break;
+        case 0x03:  /* x >  y >= k >= z */
+            o1 = X1; o2 = Y1; o3 = K1; m1 = rx; m2 = ry; m3 = rk; m4 = rz; break;
+        case 0x05:  /* x >= z >= y >= k */
+            o1 = X1; o2 = Z1; o3 = Y1; m1 = rx; m2 = rz; m3 = ry; m4 = rk; break;
+        case 0x06:  /* y >= x >= z >  k */
+            o1 = Y1; o2 = X1; o3 = Z1; m1 = ry; m2 = rx; m3 = rz; m4 = rk; break;
+        case 0x07:  /* x >  y >  z >  k */
+            o1 = X1; o2 = Y1; o3 = Z1; m1 = rx; m2 = ry; m3 = rz; m4 = rk; break;
+        case 0x0a:  /* y >= k >  x >= z */
+            o1 = Y1; o2 = K1; o3 = X1; m1 = ry; m2 = rk; m3 = rx; m4 = rz; break;
+        case 0x14:  /* z >= y >= x >= k */
+            o1 = Z1; o2 = Y1; o3 = X1; m1 = rz; m2 = ry; m3 = rx; m4 = rk; break;
+        case 0x15:  /* z >  x >= y >= k */
+            o1 = Z1; o2 = X1; o3 = Y1; m1 = rz; m2 = rx; m3 = ry; m4 = rk; break;
+        case 0x16:  /* y >= z >  x >= k */
+            o1 = Y1; o2 = Z1; o3 = X1; m1 = ry; m2 = rz; m3 = rx; m4 = rk; break;
+        case 0x1a:  /* y >= k >= z >  x */
+            o1 = Y1; o2 = K1; o3 = Z1; m1 = ry; m2 = rk; m3 = rz; m4 = rx; break;
+        case 0x1c:  /* z >= y >= k >  x */
+            o1 = Z1; o2 = Y1; o3 = K1; m1 = rz; m2 = ry; m3 = rk; m4 = rx; break;
+        case 0x1e:  /* y >  z >  k >  x */
+            o1 = Y1; o2 = Z1; o3 = K1; m1 = ry; m2 = rz; m3 = rk; m4 = rx; break;
+        case 0x21:  /* x >= k >= z >= y */
+            o1 = X1; o2 = K1; o3 = Z1; m1 = rx; m2 = rk; m3 = rz; m4 = ry; break;
+        case 0x23:  /* x >= k >  y >  z */
+            o1 = X1; o2 = K1; o3 = Y1; m1 = rx; m2 = rk; m3 = ry; m4 = rz; break;
+        case 0x25:  /* x >= z >  k >  y */
+            o1 = X1; o2 = Z1; o3 = K1; m1 = rx; m2 = rz; m3 = rk; m4 = ry; break;
+        case 0x29:  /* k >  x >= z >= y */
+            o1 = K1; o2 = X1; o3 = Z1; m1 = rk; m2 = rx; m3 = rz; m4 = ry; break;
+        case 0x2a:  /* k >  y >= x >= z */
+            o1 = K1; o2 = Y1; o3 = X1; m1 = rk; m2 = ry; m3 = rx; m4 = rz; break;
+        case 0x2b:  /* k >  x >  y >  z */
+            o1 = K1; o2 = X1; o3 = Y1; m1 = rk; m2 = rx; m3 = ry; m4 = rz; break;
+        case 0x35:  /* z >  x >= k >  y */
+            o1 = Z1; o2 = X1; o3 = K1; m1 = rz; m2 = rx; m3 = rk; m4 = ry; break;
+        case 0x38:  /* k >= z >= y >= x */
+            o1 = K1; o2 = Z1; o3 = Y1; m1 = rk; m2 = rz; m3 = ry; m4 = rx; break;
+        case 0x39:  /* k >= z >  x >  y */
+            o1 = K1; o2 = Z1; o3 = X1; m1 = rk; m2 = rz; m3 = rx; m4 = ry; break;
+        case 0x3a:  /* k >  y >  z >  x */
+            o1 = K1; o2 = Y1; o3 = Z1; m1 = rk; m2 = ry; m3 = rz; m4 = rx; break;
+        case 0x3c:  /* z >  k >  y >= x */
+            o1 = Z1; o2 = K1; o3 = Y1; m1 = rz; m2 = rk; m3 = ry; m4 = rx; break;
+        case 0x3d:  /* z >  k >  x >  y */
+            o1 = Z1; o2 = K1; o3 = X1; m1 = rz; m2 = rk; m3 = rx; m4 = ry; break;
     }
+    assert(m1 >= m2 && m2 >= m3 && m3 >= m4);
     o2 += o1;
     o3 += o2;
     for (OutChan=TotalOut; OutChan != 0; OutChan--) {
@@ -1138,6 +1150,29 @@ void Eval4InputsFloat(cmsContext ContextID, const cmsFloat32Number Input[],
 
         *Out++ = c0 + c1 * m1 + c2 * m2 + c3 * m3 + c4 * m4;
     }
+    return;
+
+two_lerps:
+    assert(m1 >= m2);
+    for (OutChan=TotalOut; OutChan != 0; OutChan--) {
+        c1 = LutTable[o1];
+        c2 = LutTable[o4] - c1;
+        c0 = *LutTable++;
+        c1 -= c0;
+
+        *Out++ = c0 + c1 * m1 + c2 * m2;
+    }
+    return;
+
+one_lerp:
+    for (OutChan=TotalOut; OutChan != 0; OutChan--) {
+        c1 = LutTable[o4];
+        c0 = *LutTable++;
+        c1 -= c0;
+
+        *Out++ = c0 + c1 * m1;
+    }
+    return;
 }
 
 static CMS_NO_SANITIZE

----------------------------------------------------------------------
commit 1cc72912138544dcf00ed0dbc77ceaf47de04e91
Author: Robin Watts <[email protected]>
Date:   Fri Sep 6 18:04:17 2019 +0100

    Tweak Eval4Inputs for speed.
    
    In coding the SSE version for CAL, I spotted a slightly
    preferable test that allows us to capture some special
    cases for free. These special cases accelerate some
    useful cases including:
    
     * C=M=Y=K (such as when all 0 = white?)
     * C=M=Y   (such as when pure black)
     * M=Y=K   (possibly useful in case we ever have profiles that
                store K first).

diff --git a/lcms2mt/src/cmsintrp.c b/lcms2mt/src/cmsintrp.c
index d1fe0b2..f4f22be 100644
--- a/lcms2mt/src/cmsintrp.c
+++ b/lcms2mt/src/cmsintrp.c
@@ -846,7 +846,7 @@ void TetrahedralInterp16(cmsContext ContextID, register const cmsUInt16Number In
 }
 
 
-/* Hyper-Pentahedral Interpolation */
+/* Pentachoronal Interpolation */
 static CMS_NO_SANITIZE
 void Eval4Inputs(cmsContext ContextID, register const cmsUInt16Number Input[],
                      register cmsUInt16Number Output[],
@@ -895,69 +895,81 @@ void Eval4Inputs(cmsContext ContextID, register const cmsUInt16Number Input[],
     LutTable = (cmsUInt16Number*) p16 -> Table;
     LutTable += K0 + X0 + Y0 + Z0;
 
-    which = (ry > rx ?  1 : 0) +
-            (rz > rx ?  2 : 0) +
-            (rk > rx ?  4 : 0) +
-            (rz > ry ?  8 : 0) +
-            (rk > ry ? 16 : 0) +
-            (rk > rz ? 32 : 0);
-    /* This gives us 24 possible cases:
-     * which                        Tetrahedral corners
-     * 0x00  rx >= ry >= rz >= rk   (0,0,0,0) (1,0,0,0) (1,1,0,0) (1,1,1,0) (1,1,1,1)
-     * 0x01  ry >  rx >= rz >= rk   (0,0,0,0) (0,1,0,0) (1,1,0,0) (1,1,1,0) (1,1,1,1)
-     * 0x03  ry >= rz >  rx >= rk   (0,0,0,0) (0,1,0,0) (0,1,1,0) (1,1,1,0) (1,1,1,1)
-     * 0x07  ry >= rz >= rk >  rx   (0,0,0,0) (0,1,0,0) (0,1,1,0) (0,1,1,1) (1,1,1,1)
-     * 0x08  rx >= rz >  ry >= rk   (0,0,0,0) (1,0,0,0) (1,0,1,0) (1,1,1,0) (1,1,1,1)
-     * 0x0a  rz >  rx >= ry >= rk   (0,0,0,0) (0,0,1,0) (1,0,1,0) (1,1,1,0) (1,1,1,1)
-     * 0x0b  rz >  ry >  rx >= rk   (0,0,0,0) (0,0,1,0) (0,1,1,0) (1,1,1,0) (1,1,1,1)
-     * 0x0f  rz >  ry >= rk >  rx   (0,0,0,0) (0,0,1,0) (0,1,1,0) (0,1,1,1) (1,1,1,1)
-     * 0x18  rx >= rz >= rk >  ry   (0,0,0,0) (1,0,0,0) (1,0,1,0) (1,0,1,1) (1,1,1,1)
-     * 0x1a  rz >  rx >= rk >  ry   (0,0,0,0) (0,0,1,0) (1,0,1,0) (1,0,1,1) (1,1,1,1)
-     * 0x1e  rz >= rk >  rx >= ry   (0,0,0,0) (0,0,1,0) (0,0,1,1) (1,0,1,1) (1,1,1,1)
-     * 0x1f  rz >= rk >  ry >  rx   (0,0,0,0) (0,0,1,0) (0,0,1,1) (0,1,1,1) (1,1,1,1)
-     * 0x20  rx >= ry >= rk >  rz   (0,0,0,0) (1,0,0,0) (1,1,0,0) (1,1,0,1) (1,1,1,1)
-     * 0x21  ry >  rx >= rk >  rz   (0,0,0,0) (0,1,0,0) (1,1,0,0) (1,1,0,1) (1,1,1,1)
-     * 0x25  ry >= rk >  rx >= rz   (0,0,0,0) (0,1,0,0) (0,1,0,1) (1,1,0,1) (1,1,1,1)
-     * 0x27  ry >= rk >  rz >  rx   (0,0,0,0) (0,1,0,0) (0,1,0,1) (0,1,1,1) (1,1,1,1)
-     * 0x30  rx >= rk >  ry >= rz   (0,0,0,0) (1,0,0,0) (1,0,0,1) (1,1,0,1) (1,1,1,1)
-     * 0x34  rk >  rx >= ry >= rz   (0,0,0,0) (0,0,0,1) (1,0,0,1) (1,1,0,1) (1,1,1,1)
-     * 0x35  rk >  ry >  rx >= rz   (0,0,0,0) (0,0,0,1) (0,1,0,1) (1,1,0,1) (1,1,1,1)
-     * 0x37  rk >  ry >= rz >  rx   (0,0,0,0) (0,0,0,1) (0,1,0,1) (0,1,1,1) (1,1,1,1)
-     * 0x38  rx >= rk >  rz >  ry   (0,0,0,0) (1,0,0,0) (1,0,0,1) (1,0,1,1) (1,1,1,1)
-     * 0x3c  rk >  rx >= rz >  ry   (0,0,0,0) (0,0,0,1) (1,0,0,1) (1,0,1,1) (1,1,1,1)
-     * 0x3e  rk >  rz >  rx >= ry   (0,0,0,0) (0,0,0,1) (0,0,1,1) (1,0,1,1) (1,1,1,1)
-     * 0x3f  rk >  rz >  ry  > rx   (0,0,0,0) (0,0,0,1) (0,0,1,1) (0,1,1,1) (1,1,1,1)
-     */
-    
+    /* We carefully choose the following tests, a) cos these
+     * work nicely in SSE (see CAL), and b) because, as well
+     * as the standard 24 pentachorons, we get some useful
+     * special cases. */
+    which = (rx > ry ?  1 : 0) +
+            (ry > rz ?  2 : 0) +
+            (rz > rk ?  4 : 0) +
+            (rk > rx ?  8 : 0) +
+            (rz > rx ? 16 : 0) +
+            (rk > ry ? 32 : 0);
+
     o4 = X1+Y1+Z1+K1;
     switch(which)
     {
-        default: /* Never happens, but stops the compiler complaining of uninitialised vars */
-        case 0x00: o1 = X1; o2 = Y1; o3 = Z1; m1 = rx; m2 = ry; m3 = rz; m4 = rk; break;
-        case 0x01: o1 = Y1; o2 = X1; o3 = Z1; m1 = ry; m2 = rx; m3 = rz; m4 = rk; break;
-        case 0x03: o1 = Y1; o2 = Z1; o3 = X1; m1 = ry; m2 = rz; m3 = rx; m4 = rk; break;
-        case 0x07: o1 = Y1; o2 = Z1; o3 = K1; m1 = ry; m2 = rz; m3 = rk; m4 = rx; break;
-        case 0x08: o1 = X1; o2 = Z1; o3 = Y1; m1 = rx; m2 = rz; m3 = ry; m4 = rk; break;
-        case 0x0a: o1 = Z1; o2 = X1; o3 = Y1; m1 = rz; m2 = rx; m3 = ry; m4 = rk; break;
-        case 0x0b: o1 = Z1; o2 = Y1; o3 = X1; m1 = rz; m2 = ry; m3 = rx; m4 = rk; break;
-        case 0x0f: o1 = Z1; o2 = Y1; o3 = K1; m1 = rz; m2 = ry; m3 = rk; m4 = rx; break;
-        case 0x18: o1 = X1; o2 = Z1; o3 = K1; m1 = rx; m2 = rz; m3 = rk; m4 = ry; break;
-        case 0x1a: o1 = Z1; o2 = X1; o3 = K1; m1 = rz; m2 = rx; m3 = rk; m4 = ry; break;
-        case 0x1e: o1 = Z1; o2 = K1; o3 = X1; m1 = rz; m2 = rk; m3 = rx; m4 = ry; break;
-        case 0x1f: o1 = Z1; o2 = K1; o3 = Y1; m1 = rz; m2 = rk; m3 = ry; m4 = rx; break;
-        case 0x20: o1 = X1; o2 = Y1; o3 = K1; m1 = rx; m2 = ry; m3 = rk; m4 = rz; break;
-        case 0x21: o1 = Y1; o2 = X1; o3 = K1; m1 = ry; m2 = rx; m3 = rk; m4 = rz; break;
-        case 0x25: o1 = Y1; o2 = K1; o3 = X1; m1 = ry; m2 = rk; m3 = rx; m4 = rz; break;
-        case 0x27: o1 = Y1; o2 = K1; o3 = Z1; m1 = ry; m2 = rk; m3 = rz; m4 = rx; break;
-        case 0x30: o1 = X1; o2 = K1; o3 = Y1; m1 = rx; m2 = rk; m3 = ry; m4 = rz; break;
-        case 0x34: o1 = K1; o2 = X1; o3 = Y1; m1 = rk; m2 = rx; m3 = ry; m4 = rz; break;
-        case 0x35: o1 = K1; o2 = Y1; o3 = X1; m1 = rk; m2 = ry; m3 = rx; m4 = rz; break;
-        case 0x37: o1 = K1; o2 = Y1; o3 = Z1; m1 = rk; m2 = ry; m3 = rz; m4 = rx; break;
-        case 0x38: o1 = X1; o2 = K1; o3 = Z1; m1 = rx; m2 = rk; m3 = rz; m4 = ry; break;
-        case 0x3c: o1 = K1; o2 = X1; o3 = Z1; m1 = rk; m2 = rx; m3 = rz; m4 = ry; break;
-        case 0x3e: o1 = K1; o2 = Z1; o3 = X1; m1 = rk; m2 = rz; m3 = rx; m4 = ry; break;
-        case 0x3f: o1 = K1; o2 = Z1; o3 = Y1; m1 = rk; m2 = rz; m3 = ry; m4 = rx; break;
+        default:    /* Never happens, but stops the compiler complaining of uninitialised vars */
+        case 0x00:  /* x == y == z == k - special case */
+            m1 = rx; goto one_lerp;
+        case 0x01:  /* x >  k == z == y - special case */
+            o1 = X1;       m1 = rx; m2 = ry; goto two_lerps;
+        case 0x18:  /* y == z == k >  x - special case */
+            o1 = Y1+Z1+K1; m1 = ry; m2 = rx; goto two_lerps;
+        case 0x04:  /* z == y == x >  k - special case */
+            o1 = X1+Y1+Z1; m1 = ry; m2 = rk; goto two_lerps;
+        case 0x28:  /* k >  z == y == x - special case */
+            o1 = K1;       m1 = rk; m2 = ry; goto two_lerps;
+        case 0x02:  /* y >= x >= k >= z */
+            o1 = Y1; o2 = X1; o3 = K1; m1 = ry; m2 = rx; m3 = rk; m4 = rz; break;
+        case 0x03:  /* x >  y >= k >= z */
+            o1 = X1; o2 = Y1; o3 = K1; m1 = rx; m2 = ry; m3 = rk; m4 = rz; break;
+        case 0x05:  /* x >= z >= y >= k */
+            o1 = X1; o2 = Z1; o3 = Y1; m1 = rx; m2 = rz; m3 = ry; m4 = rk; break;
+        case 0x06:  /* y >= x >= z >  k */
+            o1 = Y1; o2 = X1; o3 = Z1; m1 = ry; m2 = rx; m3 = rz; m4 = rk; break;
+        case 0x07:  /* x >  y >  z >  k */
+            o1 = X1; o2 = Y1; o3 = Z1; m1 = rx; m2 = ry; m3 = rz; m4 = rk; break;
+        case 0x0a:  /* y >= k >  x >= z */
+            o1 = Y1; o2 = K1; o3 = X1; m1 = ry; m2 = rk; m3 = rx; m4 = rz; break;
+        case 0x14:  /* z >= y >= x >= k */
+            o1 = Z1; o2 = Y1; o3 = X1; m1 = rz; m2 = ry; m3 = rx; m4 = rk; break;
+        case 0x15:  /* z >  x >= y >= k */
+            o1 = Z1; o2 = X1; o3 = Y1; m1 = rz; m2 = rx; m3 = ry; m4 = rk; break;
+        case 0x16:  /* y >= z >  x >= k */
+            o1 = Y1; o2 = Z1; o3 = X1; m1 = ry; m2 = rz; m3 = rx; m4 = rk; break;
+        case 0x1a:  /* y >= k >= z >  x */
+            o1 = Y1; o2 = K1; o3 = Z1; m1 = ry; m2 = rk; m3 = rz; m4 = rx; break;
+        case 0x1c:  /* z >= y >= k >  x */
+            o1 = Z1; o2 = Y1; o3 = K1; m1 = rz; m2 = ry; m3 = rk; m4 = rx; break;
+        case 0x1e:  /* y >  z >  k >  x */
+            o1 = Y1; o2 = Z1; o3 = K1; m1 = ry; m2 = rz; m3 = rk; m4 = rx; break;
+        case 0x21:  /* x >= k >= z >= y */
+            o1 = X1; o2 = K1; o3 = Z1; m1 = rx; m2 = rk; m3 = rz; m4 = ry; break;
+        case 0x23:  /* x >= k >  y >  z */
+            o1 = X1; o2 = K1; o3 = Y1; m1 = rx; m2 = rk; m3 = ry; m4 = rz; break;
+        case 0x25:  /* x >= z >  k >  y */
+            o1 = X1; o2 = Z1; o3 = K1; m1 = rx; m2 = rz; m3 = rk; m4 = ry; break;
+        case 0x29:  /* k >  x >= z >= y */
+            o1 = K1; o2 = X1; o3 = Z1; m1 = rk; m2 = rx; m3 = rz; m4 = ry; break;
+        case 0x2a:  /* k >  y >= x >= z */
+            o1 = K1; o2 = Y1; o3 = X1; m1 = rk; m2 = ry; m3 = rx; m4 = rz; break;
+        case 0x2b:  /* k >  x >  y >  z */
+            o1 = K1; o2 = X1; o3 = Y1; m1 = rk; m2 = rx; m3 = ry; m4 = rz; break;
+        case 0x35:  /* z >  x >= k >  y */
+            o1 = Z1; o2 = X1; o3 = K1; m1 = rz; m2 = rx; m3 = rk; m4 = ry; break;
+        case 0x38:  /* k >= z >= y >= x */
+            o1 = K1; o2 = Z1; o3 = Y1; m1 = rk; m2 = rz; m3 = ry; m4 = rx; break;
+        case 0x39:  /* k >= z >  x >  y */
+            o1 = K1; o2 = Z1; o3 = X1; m1 = rk; m2 = rz; m3 = rx; m4 = ry; break;
+        case 0x3a:  /* k >  y >  z >  x */
+            o1 = K1; o2 = Y1; o3 = Z1; m1 = rk; m2 = ry; m3 = rz; m4 = rx; break;
+        case 0x3c:  /* z >  k >  y >= x */
+            o1 = Z1; o2 = K1; o3 = Y1; m1 = rz; m2 = rk; m3 = ry; m4 = rx; break;
+        case 0x3d:  /* z >  k >  x >  y */
+            o1 = Z1; o2 = K1; o3 = X1; m1 = rz; m2 = rk; m3 = rx; m4 = ry; break;
     }
+    assert(m1 >= m2 && m2 >= m3 && m3 >= m4);
     o2 += o1;
     o3 += o2;
     for (OutChan=p16 -> nOutputs; OutChan != 0; OutChan--) {
@@ -974,6 +986,33 @@ void Eval4Inputs(cmsContext ContextID, register const cmsUInt16Number Input[],
 
         *Out++ = (cmsUInt16Number)(c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
     }
+    return;
+
+two_lerps:
+    assert(m1 >= m2);
+    for (OutChan=p16 -> nOutputs; OutChan != 0; OutChan--) {
+        c1 = LutTable[o1];
+        c2 = LutTable[o4] - c1;
+        c0 = *LutTable++;
+        c1 -= c0;
+
+        Rest = c1 * m1 + c2 * m2;
+
+        *Out++ = (cmsUInt16Number)(c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
+    }
+    return;
+
+one_lerp:
+    for (OutChan=p16 -> nOutputs; OutChan != 0; OutChan--) {
+        c1 = LutTable[o4];
+        c0 = *LutTable++;
+        c1 -= c0;
+
+        Rest = c1 * m1;
+
+        *Out++ = (cmsUInt16Number)(c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
+    }
+    return;
 }
 
 static

----------------------------------------------------------------------
commit 3f46434c0fe3707f53a825f39fa1bab8c0875c03
Author: Robin Watts <[email protected]>
Date:   Fri Sep 6 17:10:22 2019 +0100

    Update CAL initialisation to register second lcms2mt plugin.
    
    The first plugin deals with transformations. The second deals
    with interpolation.

diff --git a/base/gsicc_lcms2mt.c b/base/gsicc_lcms2mt.c
index ff128ee..1748b16 100644
--- a/base/gsicc_lcms2mt.c
+++ b/base/gsicc_lcms2mt.c
@@ -877,6 +877,7 @@ gscms_create(gs_memory_t *memory)
 
 #ifdef WITH_CAL
     cmsPlugin(ctx, cal_cms_extensions());
+    cmsPlugin(ctx, cal_cms_extensions2());
 #endif
 
     cmsSetLogErrorHandler(ctx, gscms_error);


Summary of changes:
 base/gsicc_lcms2mt.c   |   1 +
 lcms2mt/src/cmsintrp.c | 698 ++++++++++++++++++++++++-------------------------
 2 files changed, 349 insertions(+), 350 deletions(-)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.