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