1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//---------------------------------------------------------------------------------
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//  Little Color Management System
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//  Copyright (c) 1998-2012 Marti Maria Saguer
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Permission is hereby granted, free of charge, to any person obtaining
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// a copy of this software and associated documentation files (the "Software"),
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// to deal in the Software without restriction, including without limitation
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// and/or sell copies of the Software, and to permit persons to whom the Software
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// is furnished to do so, subject to the following conditions:
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The above copyright notice and this permission notice shall be included in
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// all copies or substantial portions of the Software.
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//---------------------------------------------------------------------------------
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "lcms2_internal.h"
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This module incorporates several interpolation routines, for 1 to 8 channels on input and
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// up to 65535 channels on output. The user may change those by using the interpolation plug-in
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Interpolation routines by default
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is the default factory
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsInterpPluginChunkType _cmsInterpPluginChunk = { NULL };
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The interpolation plug-in memory chunk allocator/dup
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src)
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void* from;
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(ctx != NULL);
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src != NULL) {
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        from = src ->chunks[InterpPlugin];
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        static _cmsInterpPluginChunkType InterpPluginChunk = { NULL };
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        from = &InterpPluginChunk;
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(from != NULL);
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ctx ->chunks[InterpPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsInterpPluginChunkType));
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Main plug-in entry
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Data)
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Data == NULL) {
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ptr ->Interpolators = NULL;
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Set replacement functions
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ptr ->Interpolators = Plugin ->InterpolatorsFactory;
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Set the interpolation method
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p)
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p ->Interpolation.Lerp16 = NULL;
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   // Invoke factory, possibly in the Plug-in
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ptr ->Interpolators != NULL)
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p ->Interpolation = ptr->Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // If unsupported by the plug-in, go for the LittleCMS default.
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // If happens only if an extern plug-in is being used
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p ->Interpolation.Lerp16 == NULL)
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p ->Interpolation = DefaultInterpolatorsFactory(p ->nInputs, p ->nOutputs, p ->dwFlags);
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Check for valid interpolator (we just check one member of the union)
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p ->Interpolation.Lerp16 == NULL) {
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This function precalculates as many parameters as possible to speed up the interpolation.
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                           const cmsUInt32Number nSamples[],
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                           int InputChan, int OutputChan,
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                           const void *Table,
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                           cmsUInt32Number dwFlags)
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsInterpParams* p;
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i;
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Check for maximum inputs
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (InputChan > MAX_INPUT_DIMENSIONS) {
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", InputChan, MAX_INPUT_DIMENSIONS);
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return NULL;
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Creates an empty object
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams));
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p == NULL) return NULL;
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Keep original parameters
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p -> dwFlags  = dwFlags;
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p -> nInputs  = InputChan;
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p -> nOutputs = OutputChan;
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p ->Table     = Table;
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p ->ContextID  = ContextID;
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Fill samples per input direction and domain (which is number of nodes minus one)
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < InputChan; i++) {
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p -> nSamples[i] = nSamples[i];
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p -> Domain[i]   = nSamples[i] - 1;
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Compute factors to apply to each component to index the grid array
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p -> opta[0] = p -> nOutputs;
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=1; i < InputChan; i++)
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsSetInterpolationRoutine(ContextID, p)) {
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(ContextID, p);
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // All seems ok
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return p;
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This one is a wrapper on the anterior, but assuming all directions have same number of nodes
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags)
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i;
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Fill the auxiliar array
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Samples[i] = nSamples;
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Call the extended function
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags);
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Free all associated memory
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsFreeInterpParams(cmsInterpParams* p)
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p != NULL) _cmsFree(p ->ContextID, p);
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Inline fixed point interpolation
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsINLINE cmsUInt16Number LinearInterp(cmsS15Fixed16Number a, cmsS15Fixed16Number l, cmsS15Fixed16Number h)
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number dif = (cmsUInt32Number) (h - l) * a + 0x8000;
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    dif = (dif >> 16) + l;
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (cmsUInt16Number) (dif);
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//  Linear interpolation (Fixed-point optimized)
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid LinLerp1D(register const cmsUInt16Number Value[],
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               register cmsUInt16Number Output[],
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               register const cmsInterpParams* p)
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number y1, y0;
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int cell0, rest;
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int val3;
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // if last value...
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Value[0] == 0xffff) {
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Output[0] = LutTable[p -> Domain[0]];
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    val3 = p -> Domain[0] * Value[0];
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    val3 = _cmsToFixedDomain(val3);    // To fixed 15.16
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cell0 = FIXED_TO_INT(val3);             // Cell is 16 MSB bits
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rest  = FIXED_REST_TO_INT(val3);        // Rest is 16 LSB bits
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y0 = LutTable[cell0];
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y1 = LutTable[cell0+1];
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Output[0] = LinearInterp(rest, y0, y1);
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// To prevent out of bounds indexing
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v)
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return v < 0.0f ? 0.0f : (v > 1.0f ? 1.0f : v);
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Floating-point version of 1D interpolation
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid LinLerp1Dfloat(const cmsFloat32Number Value[],
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmsFloat32Number Output[],
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    const cmsInterpParams* p)
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number y1, y0;
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number val2, rest;
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int cell0, cell1;
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       val2 = fclamp(Value[0]);
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       // if last value...
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       if (val2 == 1.0) {
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Output[0] = LutTable[p -> Domain[0]];
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           return;
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       val2 *= p -> Domain[0];
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cell0 = (int) floor(val2);
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cell1 = (int) ceil(val2);
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       // Rest is 16 LSB bits
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rest = val2 - cell0;
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       y0 = LutTable[cell0] ;
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       y1 = LutTable[cell1] ;
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Output[0] = y0 + (y1 - y0) * rest;
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Eval gray LUT having only one input channel
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval1Input(register const cmsUInt16Number Input[],
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                register cmsUInt16Number Output[],
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                register const cmsInterpParams* p16)
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number fk;
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number k0, k1, rk, K0, K1;
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int v;
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number OutChan;
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       v = Input[0] * p16 -> Domain[0];
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       fk = _cmsToFixedDomain(v);
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = FIXED_TO_INT(fk);
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p16 -> opta[0] * k0;
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = p16 -> opta[0] * k1;
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Eval gray LUT having only one input channel
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval1InputFloat(const cmsFloat32Number Value[],
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     cmsFloat32Number Output[],
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     const cmsInterpParams* p)
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number y1, y0;
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number val2, rest;
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int cell0, cell1;
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number OutChan;
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    val2 = fclamp(Value[0]);
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // if last value...
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       if (val2 == 1.0) {
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Output[0] = LutTable[p -> Domain[0]];
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           return;
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       val2 *= p -> Domain[0];
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cell0 = (int) floor(val2);
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cell1 = (int) ceil(val2);
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       // Rest is 16 LSB bits
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rest = val2 - cell0;
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cell0 *= p -> opta[0];
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cell1 *= p -> opta[0];
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (OutChan=0; OutChan < p->nOutputs; OutChan++) {
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            y0 = LutTable[cell0 + OutChan] ;
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            y1 = LutTable[cell1 + OutChan] ;
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Output[OutChan] = y0 + (y1 - y0) * rest;
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Bilinear interpolation (16 bits) - cmsFloat32Number version
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid BilinearInterpFloat(const cmsFloat32Number Input[],
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         cmsFloat32Number Output[],
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         const cmsInterpParams* p)
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   define LERP(a,l,h)    (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   define DENS(i,j)      (LutTable[(i)+(j)+OutChan])
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number      px, py;
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int        x0, y0,
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               X0, Y0, X1, Y1;
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int        TotalOut, OutChan;
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number      fx, fy,
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d00, d01, d10, d11,
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx0, dx1,
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxy;
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TotalOut   = p -> nOutputs;
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    px = fclamp(Input[0]) * p->Domain[0];
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    py = fclamp(Input[1]) * p->Domain[1];
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X0 = p -> opta[1] * x0;
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[1]);
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y0 = p -> opta[0] * y0;
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[0]);
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d00 = DENS(X0, Y0);
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d01 = DENS(X0, Y1);
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d10 = DENS(X1, Y0);
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d11 = DENS(X1, Y1);
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx0 = LERP(fx, d00, d10);
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx1 = LERP(fx, d01, d11);
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxy = LERP(fy, dx0, dx1);
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Output[OutChan] = dxy;
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   undef LERP
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   undef DENS
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Bilinear interpolation (16 bits) - optimized version
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid BilinearInterp16(register const cmsUInt16Number Input[],
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      register cmsUInt16Number Output[],
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      register const cmsInterpParams* p)
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DENS(i,j) (LutTable[(i)+(j)+OutChan])
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define LERP(a,l,h)     (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           int        OutChan, TotalOut;
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           cmsS15Fixed16Number    fx, fy;
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  register int        rx, ry;
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           int        x0, y0;
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  register int        X0, X1, Y0, Y1;
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           int        d00, d01, d10, d11,
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      dx0, dx1,
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      dxy;
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TotalOut   = p -> nOutputs;
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x0  = FIXED_TO_INT(fx);
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rx  = FIXED_REST_TO_INT(fx);    // Rest in 0..1.0 domain
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y0  = FIXED_TO_INT(fy);
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ry  = FIXED_REST_TO_INT(fy);
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X0 = p -> opta[1] * x0;
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[1]);
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y0 = p -> opta[0] * y0;
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[0]);
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d00 = DENS(X0, Y0);
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d01 = DENS(X0, Y1);
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d10 = DENS(X1, Y0);
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d11 = DENS(X1, Y1);
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx0 = LERP(rx, d00, d10);
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx1 = LERP(rx, d01, d11);
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxy = LERP(ry, dx0, dx1);
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Output[OutChan] = (cmsUInt16Number) dxy;
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   undef LERP
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   undef DENS
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Trilinear interpolation (16 bits) - cmsFloat32Number version
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid TrilinearInterpFloat(const cmsFloat32Number Input[],
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                          cmsFloat32Number Output[],
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                          const cmsInterpParams* p)
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   define LERP(a,l,h)      (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   define DENS(i,j,k)      (LutTable[(i)+(j)+(k)+OutChan])
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number      px, py, pz;
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int        x0, y0, z0,
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               X0, Y0, Z0, X1, Y1, Z1;
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int        TotalOut, OutChan;
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number      fx, fy, fz,
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d000, d001, d010, d011,
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d100, d101, d110, d111,
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx00, dx01, dx10, dx11,
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxy0, dxy1, dxyz;
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TotalOut   = p -> nOutputs;
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // We need some clipping here
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    px = fclamp(Input[0]) * p->Domain[0];
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    py = fclamp(Input[1]) * p->Domain[1];
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pz = fclamp(Input[2]) * p->Domain[2];
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0;
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X0 = p -> opta[2] * x0;
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y0 = p -> opta[1] * y0;
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z0 = p -> opta[0] * z0;
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d000 = DENS(X0, Y0, Z0);
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d001 = DENS(X0, Y0, Z1);
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d010 = DENS(X0, Y1, Z0);
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d011 = DENS(X0, Y1, Z1);
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d100 = DENS(X1, Y0, Z0);
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d101 = DENS(X1, Y0, Z1);
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d110 = DENS(X1, Y1, Z0);
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d111 = DENS(X1, Y1, Z1);
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx00 = LERP(fx, d000, d100);
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx01 = LERP(fx, d001, d101);
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx10 = LERP(fx, d010, d110);
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx11 = LERP(fx, d011, d111);
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxy0 = LERP(fy, dx00, dx10);
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxy1 = LERP(fy, dx01, dx11);
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxyz = LERP(fz, dxy0, dxy1);
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Output[OutChan] = dxyz;
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   undef LERP
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   undef DENS
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Trilinear interpolation (16 bits) - optimized version
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid TrilinearInterp16(register const cmsUInt16Number Input[],
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       register cmsUInt16Number Output[],
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       register const cmsInterpParams* p)
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define LERP(a,l,h)     (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           int        OutChan, TotalOut;
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           cmsS15Fixed16Number    fx, fy, fz;
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  register int        rx, ry, rz;
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           int        x0, y0, z0;
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  register int        X0, X1, Y0, Y1, Z0, Z1;
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           int        d000, d001, d010, d011,
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      d100, d101, d110, d111,
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      dx00, dx01, dx10, dx11,
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      dxy0, dxy1, dxyz;
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TotalOut   = p -> nOutputs;
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x0  = FIXED_TO_INT(fx);
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rx  = FIXED_REST_TO_INT(fx);    // Rest in 0..1.0 domain
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y0  = FIXED_TO_INT(fy);
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ry  = FIXED_REST_TO_INT(fy);
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    z0 = FIXED_TO_INT(fz);
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rz = FIXED_REST_TO_INT(fz);
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X0 = p -> opta[2] * x0;
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y0 = p -> opta[1] * y0;
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z0 = p -> opta[0] * z0;
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d000 = DENS(X0, Y0, Z0);
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d001 = DENS(X0, Y0, Z1);
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d010 = DENS(X0, Y1, Z0);
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d011 = DENS(X0, Y1, Z1);
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d100 = DENS(X1, Y0, Z0);
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d101 = DENS(X1, Y0, Z1);
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d110 = DENS(X1, Y1, Z0);
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d111 = DENS(X1, Y1, Z1);
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx00 = LERP(rx, d000, d100);
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx01 = LERP(rx, d001, d101);
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx10 = LERP(rx, d010, d110);
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dx11 = LERP(rx, d011, d111);
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxy0 = LERP(ry, dx00, dx10);
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxy1 = LERP(ry, dx01, dx11);
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dxyz = LERP(rz, dxy0, dxy1);
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Output[OutChan] = (cmsUInt16Number) dxyz;
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   undef LERP
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#   undef DENS
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Tetrahedral interpolation, using Sakamoto algorithm.
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid TetrahedralInterpFloat(const cmsFloat32Number Input[],
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            cmsFloat32Number Output[],
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            const cmsInterpParams* p)
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number     px, py, pz;
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int        x0, y0, z0,
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               X0, Y0, Z0, X1, Y1, Z1;
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number     rx, ry, rz;
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number     c0, c1=0, c2=0, c3=0;
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int                  OutChan, TotalOut;
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TotalOut   = p -> nOutputs;
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // We need some clipping here
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    px = fclamp(Input[0]) * p->Domain[0];
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    py = fclamp(Input[1]) * p->Domain[1];
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pz = fclamp(Input[2]) * p->Domain[2];
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0);
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0);
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0);
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X0 = p -> opta[2] * x0;
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y0 = p -> opta[1] * y0;
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z0 = p -> opta[0] * z0;
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (OutChan=0; OutChan < TotalOut; OutChan++) {
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       // These are the 6 Tetrahedral
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        c0 = DENS(X0, Y0, Z0);
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (rx >= ry && ry >= rz) {
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            c1 = DENS(X1, Y0, Z0) - c0;
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (rx >= rz && rz >= ry) {
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 = DENS(X1, Y0, Z0) - c0;
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            else
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (rz >= rx && rx >= ry) {
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    c3 = DENS(X0, Y0, Z1) - c0;
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                else
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (ry >= rx && rx >= rz) {
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        c2 = DENS(X0, Y1, Z0) - c0;
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    else
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if (ry >= rz && rz >= rx) {
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            c2 = DENS(X0, Y1, Z0) - c0;
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        }
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        else
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            if (rz >= ry && ry >= rx) {
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c3 = DENS(X0, Y0, Z1) - c0;
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            }
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            else  {
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c1 = c2 = c3 = 0;
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            }
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef DENS
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid TetrahedralInterp16(register const cmsUInt16Number Input[],
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         register cmsUInt16Number Output[],
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         register const cmsInterpParams* p)
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number fx, fy, fz;
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number rx, ry, rz;
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int x0, y0, z0;
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number c0, c1, c2, c3, Rest;
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number TotalOut = p -> nOutputs;
704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x0 = FIXED_TO_INT(fx);
710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y0 = FIXED_TO_INT(fy);
711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    z0 = FIXED_TO_INT(fz);
712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rx = FIXED_REST_TO_INT(fx);
714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ry = FIXED_REST_TO_INT(fy);
715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rz = FIXED_REST_TO_INT(fz);
716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X0 = p -> opta[2] * x0;
718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X1 = (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y0 = p -> opta[1] * y0;
721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y1 = (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z0 = p -> opta[0] * z0;
724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    LutTable = &LutTable[X0+Y0+Z0];
727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // This can be replaced by: t = Rest+0x8001, x = (t + (t>>16))>>16
731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // at the cost of being off by one at 7fff and 17ffe.
732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (rx >= ry) {
734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (ry >= rz) {
735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Y1 += X1;
736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Z1 += Y1;
737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (; TotalOut; TotalOut--) {
738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 = LutTable[X1];
739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 = LutTable[Y1];
740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 = LutTable[Z1];
741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c0 = *LutTable++;
742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 -= c2;
743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 -= c1;
744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 -= c0;
745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (rz >= rx) {
749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            X1 += Z1;
750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Y1 += X1;
751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (; TotalOut; TotalOut--) {
752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 = LutTable[X1];
753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 = LutTable[Y1];
754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 = LutTable[Z1];
755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c0 = *LutTable++;
756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 -= c1;
757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 -= c3;
758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 -= c0;
759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Z1 += X1;
764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Y1 += Z1;
765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (; TotalOut; TotalOut--) {
766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 = LutTable[X1];
767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 = LutTable[Y1];
768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 = LutTable[Z1];
769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c0 = *LutTable++;
770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 -= c3;
771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 -= c1;
772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 -= c0;
773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (rx >= rz) {
779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            X1 += Y1;
780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Z1 += X1;
781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (; TotalOut; TotalOut--) {
782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 = LutTable[X1];
783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 = LutTable[Y1];
784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 = LutTable[Z1];
785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c0 = *LutTable++;
786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 -= c1;
787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 -= c2;
788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 -= c0;
789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (ry >= rz) {
793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Z1 += Y1;
794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            X1 += Z1;
795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (; TotalOut; TotalOut--) {
796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 = LutTable[X1];
797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 = LutTable[Y1];
798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 = LutTable[Z1];
799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c0 = *LutTable++;
800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 -= c3;
801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 -= c2;
802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 -= c0;
803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Y1 += Z1;
808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            X1 += Y1;
809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (; TotalOut; TotalOut--) {
810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 = LutTable[X1];
811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 = LutTable[Y1];
812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 = LutTable[Z1];
813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c0 = *LutTable++;
814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 -= c2;
815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 -= c3;
816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 -= c0;
817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval4Inputs(register const cmsUInt16Number Input[],
828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     register cmsUInt16Number Output[],
829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     register const cmsInterpParams* p16)
830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const cmsUInt16Number* LutTable;
832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number fk;
833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number k0, rk;
834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int K0, K1;
835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number    fx, fy, fz;
836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number    rx, ry, rz;
837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int                    x0, y0, z0;
838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number    X0, X1, Y0, Y1, Z0, Z1;
839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsS15Fixed16Number    c0, c1, c2, c3, Rest;
841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number        OutChan;
842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number        Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fk  = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]);
846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fx  = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]);
847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fy  = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]);
848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fz  = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]);
849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    k0  = FIXED_TO_INT(fk);
851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x0  = FIXED_TO_INT(fx);
852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y0  = FIXED_TO_INT(fy);
853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    z0  = FIXED_TO_INT(fz);
854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rk  = FIXED_REST_TO_INT(fk);
856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rx  = FIXED_REST_TO_INT(fx);
857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ry  = FIXED_REST_TO_INT(fy);
858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rz  = FIXED_REST_TO_INT(fz);
859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    K0 = p16 -> opta[3] * k0;
861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]);
862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X0 = p16 -> opta[2] * x0;
864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]);
865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y0 = p16 -> opta[1] * y0;
867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]);
868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z0 = p16 -> opta[0] * z0;
870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]);
871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    LutTable = (cmsUInt16Number*) p16 -> Table;
873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    LutTable += K0;
874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        c0 = DENS(X0, Y0, Z0);
878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (rx >= ry && ry >= rz) {
880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            c1 = DENS(X1, Y0, Z0) - c0;
882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (rx >= rz && rz >= ry) {
888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 = DENS(X1, Y0, Z0) - c0;
890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            else
895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (rz >= rx && rx >= ry) {
896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    c3 = DENS(X0, Y0, Z1) - c0;
900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                else
903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (ry >= rx && rx >= rz) {
904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        c2 = DENS(X0, Y1, Z0) - c0;
907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    else
911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if (ry >= rz && rz >= rx) {
912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            c2 = DENS(X0, Y1, Z0) - c0;
915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        }
918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        else
919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            if (rz >= ry && ry >= rx) {
920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c3 = DENS(X0, Y0, Z1) - c0;
924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            }
926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            else  {
927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c1 = c2 = c3 = 0;
928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            }
929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            Rest = c1 * rx + c2 * ry + c3 * rz;
931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    LutTable = (cmsUInt16Number*) p16 -> Table;
937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    LutTable += K1;
938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        c0 = DENS(X0, Y0, Z0);
942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (rx >= ry && ry >= rz) {
944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            c1 = DENS(X1, Y0, Z0) - c0;
946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (rx >= rz && rz >= ry) {
952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c1 = DENS(X1, Y0, Z0) - c0;
954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            else
959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (rz >= rx && rx >= ry) {
960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    c3 = DENS(X0, Y0, Z1) - c0;
964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                else
967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (ry >= rx && rx >= rz) {
968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        c2 = DENS(X0, Y1, Z0) - c0;
971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    else
975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if (ry >= rz && rz >= rx) {
976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            c2 = DENS(X0, Y1, Z0) - c0;
979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        }
982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        else
983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            if (rz >= ry && ry >= rx) {
984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c3 = DENS(X0, Y0, Z1) - c0;
988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            }
990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            else  {
991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                c1 = c2 = c3 = 0;
992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            }
993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            Rest = c1 * rx + c2 * ry + c3 * rz;
995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < p16 -> nOutputs; i++) {
1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef DENS
1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// For more that 3 inputs (i.e., CMYK)
1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// evaluate two 3-dimensional interpolations and then linearly interpolate between them.
1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval4InputsFloat(const cmsFloat32Number Input[],
1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      cmsFloat32Number Output[],
1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      const cmsInterpParams* p)
1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number rest;
1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number pk;
1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int k0, K0, K1;
1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* T;
1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number i;
1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsInterpParams p1;
1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       pk = fclamp(Input[0]) * p->Domain[0];
1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = _cmsQuickFloor(pk);
1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rest = pk - (cmsFloat32Number) k0;
1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p -> opta[3] * k0;
1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]);
1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1 = *p;
1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K0;
1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       TetrahedralInterpFloat(Input + 1,  Tmp1, &p1);
1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K1;
1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       TetrahedralInterpFloat(Input + 1,  Tmp2, &p1);
1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (i=0; i < p -> nOutputs; i++)
1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       {
1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y0 = Tmp1[i];
1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y1 = Tmp2[i];
1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              Output[i] = y0 + (y1 - y0) * rest;
1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval5Inputs(register const cmsUInt16Number Input[],
1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 register cmsUInt16Number Output[],
1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 register const cmsInterpParams* p16)
1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number fk;
1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number k0, rk;
1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int K0, K1;
1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsUInt16Number* T;
1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number i;
1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsInterpParams p1;
1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = FIXED_TO_INT(fk);
1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rk = FIXED_REST_TO_INT(fk);
1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p16 -> opta[4] * k0;
1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1 = *p16;
1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K0;
1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval4Inputs(Input + 1, Tmp1, &p1);
1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K1;
1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval4Inputs(Input + 1, Tmp2, &p1);
1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (i=0; i < p16 -> nOutputs; i++) {
1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval5InputsFloat(const cmsFloat32Number Input[],
1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      cmsFloat32Number Output[],
1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      const cmsInterpParams* p)
1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number rest;
1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number pk;
1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int k0, K0, K1;
1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* T;
1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number i;
1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsInterpParams p1;
1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       pk = fclamp(Input[0]) * p->Domain[0];
1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = _cmsQuickFloor(pk);
1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rest = pk - (cmsFloat32Number) k0;
1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p -> opta[4] * k0;
1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]);
1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1 = *p;
1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K0;
1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval4InputsFloat(Input + 1,  Tmp1, &p1);
1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K1;
1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval4InputsFloat(Input + 1,  Tmp2, &p1);
1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (i=0; i < p -> nOutputs; i++) {
1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y0 = Tmp1[i];
1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y1 = Tmp2[i];
1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              Output[i] = y0 + (y1 - y0) * rest;
1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval6Inputs(register const cmsUInt16Number Input[],
1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 register cmsUInt16Number Output[],
1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 register const cmsInterpParams* p16)
1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number fk;
1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number k0, rk;
1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int K0, K1;
1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsUInt16Number* T;
1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number i;
1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsInterpParams p1;
1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = FIXED_TO_INT(fk);
1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rk = FIXED_REST_TO_INT(fk);
1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p16 -> opta[5] * k0;
1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1 = *p16;
1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K0;
1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval5Inputs(Input + 1, Tmp1, &p1);
1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K1;
1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval5Inputs(Input + 1, Tmp2, &p1);
1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (i=0; i < p16 -> nOutputs; i++) {
1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval6InputsFloat(const cmsFloat32Number Input[],
1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      cmsFloat32Number Output[],
1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      const cmsInterpParams* p)
1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number rest;
1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number pk;
1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int k0, K0, K1;
1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* T;
1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number i;
1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsInterpParams p1;
1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       pk = fclamp(Input[0]) * p->Domain[0];
1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = _cmsQuickFloor(pk);
1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rest = pk - (cmsFloat32Number) k0;
1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p -> opta[5] * k0;
1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]);
1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1 = *p;
1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K0;
1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval5InputsFloat(Input + 1,  Tmp1, &p1);
1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K1;
1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval5InputsFloat(Input + 1,  Tmp2, &p1);
1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (i=0; i < p -> nOutputs; i++) {
1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y0 = Tmp1[i];
1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y1 = Tmp2[i];
1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              Output[i] = y0 + (y1 - y0) * rest;
1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval7Inputs(register const cmsUInt16Number Input[],
1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 register cmsUInt16Number Output[],
1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 register const cmsInterpParams* p16)
1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number fk;
1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number k0, rk;
1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int K0, K1;
1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsUInt16Number* T;
1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number i;
1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsInterpParams p1;
1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = FIXED_TO_INT(fk);
1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rk = FIXED_REST_TO_INT(fk);
1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p16 -> opta[6] * k0;
1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1 = *p16;
1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K0;
1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval6Inputs(Input + 1, Tmp1, &p1);
1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K1;
1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval6Inputs(Input + 1, Tmp2, &p1);
1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (i=0; i < p16 -> nOutputs; i++) {
1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval7InputsFloat(const cmsFloat32Number Input[],
1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      cmsFloat32Number Output[],
1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      const cmsInterpParams* p)
1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number rest;
1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number pk;
1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int k0, K0, K1;
1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* T;
1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number i;
1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsInterpParams p1;
1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       pk = fclamp(Input[0]) * p->Domain[0];
1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = _cmsQuickFloor(pk);
1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rest = pk - (cmsFloat32Number) k0;
1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p -> opta[6] * k0;
1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]);
1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1 = *p;
1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K0;
1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval6InputsFloat(Input + 1,  Tmp1, &p1);
1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K1;
1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval6InputsFloat(Input + 1,  Tmp2, &p1);
1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (i=0; i < p -> nOutputs; i++) {
1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y0 = Tmp1[i];
1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y1 = Tmp2[i];
1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              Output[i] = y0 + (y1 - y0) * rest;
1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval8Inputs(register const cmsUInt16Number Input[],
1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 register cmsUInt16Number Output[],
1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 register const cmsInterpParams* p16)
1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number fk;
1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsS15Fixed16Number k0, rk;
1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int K0, K1;
1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsUInt16Number* T;
1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number i;
1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsInterpParams p1;
1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = FIXED_TO_INT(fk);
1332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rk = FIXED_REST_TO_INT(fk);
1333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p16 -> opta[7] * k0;
1335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1 = *p16;
1338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
1339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K0;
1341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval7Inputs(Input + 1, Tmp1, &p1);
1344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K1;
1346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval7Inputs(Input + 1, Tmp2, &p1);
1348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (i=0; i < p16 -> nOutputs; i++) {
1350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
1352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Eval8InputsFloat(const cmsFloat32Number Input[],
1358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      cmsFloat32Number Output[],
1359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      const cmsInterpParams* p)
1360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number rest;
1363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number pk;
1364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       int k0, K0, K1;
1365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       const cmsFloat32Number* T;
1366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt32Number i;
1367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsInterpParams p1;
1369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       pk = fclamp(Input[0]) * p->Domain[0];
1371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       k0 = _cmsQuickFloor(pk);
1372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       rest = pk - (cmsFloat32Number) k0;
1373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K0 = p -> opta[7] * k0;
1375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]);
1376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1 = *p;
1378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
1379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K0;
1381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval7InputsFloat(Input + 1,  Tmp1, &p1);
1384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       T = LutTable + K1;
1386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p1.Table = T;
1387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       Eval7InputsFloat(Input + 1,  Tmp2, &p1);
1389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (i=0; i < p -> nOutputs; i++) {
1392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y0 = Tmp1[i];
1394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsFloat32Number y1 = Tmp2[i];
1395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              Output[i] = y0 + (y1 - y0) * rest;
1397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
1398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The default factory
1401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1402ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
1403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsInterpFunction Interpolation;
1406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsBool  IsFloat     = (dwFlags & CMS_LERP_FLAGS_FLOAT);
1407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsBool  IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
1408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(&Interpolation, 0, sizeof(Interpolation));
1410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Safety check
1412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
1413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return Interpolation;
1414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch (nInputChannels) {
1416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 1: // Gray LUT / linear
1418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (nOutputChannels == 1) {
1420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   if (IsFloat)
1422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       Interpolation.LerpFloat = LinLerp1Dfloat;
1423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   else
1424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       Interpolation.Lerp16 = LinLerp1D;
1425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               }
1427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               else {
1428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   if (IsFloat)
1430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       Interpolation.LerpFloat = Eval1InputFloat;
1431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   else
1432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       Interpolation.Lerp16 = Eval1Input;
1433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               }
1434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
1435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 2: // Duotone
1437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (IsFloat)
1438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      Interpolation.LerpFloat =  BilinearInterpFloat;
1439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               else
1440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      Interpolation.Lerp16    =  BilinearInterp16;
1441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
1442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 3:  // RGB et al
1444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (IsTrilinear) {
1446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   if (IsFloat)
1448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       Interpolation.LerpFloat = TrilinearInterpFloat;
1449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   else
1450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       Interpolation.Lerp16 = TrilinearInterp16;
1451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               }
1452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               else {
1453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   if (IsFloat)
1455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       Interpolation.LerpFloat = TetrahedralInterpFloat;
1456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   else {
1457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       Interpolation.Lerp16 = TetrahedralInterp16;
1459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   }
1460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               }
1461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
1462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 4:  // CMYK lut
1464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (IsFloat)
1466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.LerpFloat =  Eval4InputsFloat;
1467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               else
1468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.Lerp16    =  Eval4Inputs;
1469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
1470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 5: // 5 Inks
1472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (IsFloat)
1473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.LerpFloat =  Eval5InputsFloat;
1474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               else
1475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.Lerp16    =  Eval5Inputs;
1476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
1477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 6: // 6 Inks
1479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (IsFloat)
1480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.LerpFloat =  Eval6InputsFloat;
1481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               else
1482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.Lerp16    =  Eval6Inputs;
1483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
1484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 7: // 7 inks
1486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (IsFloat)
1487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.LerpFloat =  Eval7InputsFloat;
1488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               else
1489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.Lerp16    =  Eval7Inputs;
1490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
1491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 8: // 8 inks
1493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (IsFloat)
1494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.LerpFloat =  Eval8InputsFloat;
1495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               else
1496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   Interpolation.Lerp16    =  Eval8Inputs;
1497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
1498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
1500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           default:
1502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               Interpolation.Lerp16 = NULL;
1503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return Interpolation;
1506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1507