GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
Teem: Tools to process and visualize scientific data and images . |
||
3 |
Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago |
||
4 |
Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann |
||
5 |
Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah |
||
6 |
|||
7 |
This library is free software; you can redistribute it and/or |
||
8 |
modify it under the terms of the GNU Lesser General Public License |
||
9 |
(LGPL) as published by the Free Software Foundation; either |
||
10 |
version 2.1 of the License, or (at your option) any later version. |
||
11 |
The terms of redistributing and/or modifying this software also |
||
12 |
include exceptions to the LGPL that facilitate static linking. |
||
13 |
|||
14 |
This library is distributed in the hope that it will be useful, |
||
15 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
17 |
Lesser General Public License for more details. |
||
18 |
|||
19 |
You should have received a copy of the GNU Lesser General Public License |
||
20 |
along with this library; if not, write to Free Software Foundation, Inc., |
||
21 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||
22 |
*/ |
||
23 |
|||
24 |
#include "nrrd.h" |
||
25 |
|||
26 |
/* |
||
27 |
** summary of information about how the kernel parameter vector is set: |
||
28 |
** Note that, annoyingly, nrrdKernelUsesScale (at end of this file) |
||
29 |
** has to be updated to record which kernels (including their derivatives) |
||
30 |
** use parm[0] for scale. |
||
31 |
|||
32 |
numParm parm[0] parm[1] parm[2] |
||
33 |
nrrdKernelHann 2 scale cut-off |
||
34 |
nrrdKernelBlackman 2 scale cut-off |
||
35 |
nrrdKernelCatmullRom 0 |
||
36 |
nrrdKernelBSpline3 0 |
||
37 |
nrrdKernelBSpline3ApproxInverse 0 |
||
38 |
nrrdKernelBSpline5 0 |
||
39 |
nrrdKernelBSpline5ApproxInverse 0 |
||
40 |
nrrdKernelBSpline7 0 |
||
41 |
nrrdKernelBSpline7ApproxInverse 0 |
||
42 |
nrrdKernelZero 1 scale |
||
43 |
nrrdKernelBox 1 scale |
||
44 |
nrrdKernelCatmullRomSupportDebug 1 support |
||
45 |
nrrdKernelBoxSupportDebug 1 support |
||
46 |
nrrdKernelCos4SupportDebug 1 support |
||
47 |
nrrdKernelCheap 1 scale |
||
48 |
nrrdKernelHermiteScaleSpaceFlag 0 |
||
49 |
nrrdKernelTent 1 scale |
||
50 |
nrrdKernelForwDiff 1 scale |
||
51 |
nrrdKernelCentDiff 1 scale |
||
52 |
nrrdKernelBCCubic 3 scale B C |
||
53 |
nrrdKernelAQuartic 2 scale A |
||
54 |
nrrdKernelC3Quintic 0 |
||
55 |
nrrdKernelC4Hexic 0 |
||
56 |
nrrdKernelC4HexicApproxInverse 0 |
||
57 |
nrrdKernelC5Septic 0 |
||
58 |
nrrdKernelGaussian 2 sigma cut-off |
||
59 |
nrrdKernelDiscreteGaussian 2 sigma cut-off |
||
60 |
nrrdKernelTMF[][][] 1 a |
||
61 |
|||
62 |
** Note that when parm[0] is named "scale", that parameter is optional, |
||
63 |
** and the default is 1.0, when given in string form |
||
64 |
** E.g. "tent" is understood as "tent:1", |
||
65 |
** but "gauss:4" isn't complete and won't parse; while "gauss:1,4" is good |
||
66 |
** See note above about nrrdKernelUsesScale (at end of this file) |
||
67 |
*/ |
||
68 |
|||
69 |
/* these functions replace what had been a lot of |
||
70 |
identical functions for similar kernels */ |
||
71 |
|||
72 |
static double |
||
73 |
returnZero(const double *parm) { |
||
74 |
AIR_UNUSED(parm); |
||
75 |
580 |
return 0.0; |
|
76 |
} |
||
77 |
|||
78 |
static double |
||
79 |
returnOne(const double *parm) { |
||
80 |
AIR_UNUSED(parm); |
||
81 |
7128 |
return 1.0; |
|
82 |
} |
||
83 |
|||
84 |
static double |
||
85 |
returnTwo(const double *parm) { |
||
86 |
AIR_UNUSED(parm); |
||
87 |
22 |
return 2.0; |
|
88 |
} |
||
89 |
|||
90 |
static double |
||
91 |
returnThree(const double *parm) { |
||
92 |
AIR_UNUSED(parm); |
||
93 |
376 |
return 3.0; |
|
94 |
} |
||
95 |
|||
96 |
static double |
||
97 |
returnFour(const double *parm) { |
||
98 |
AIR_UNUSED(parm); |
||
99 |
16 |
return 4.0; |
|
100 |
} |
||
101 |
|||
102 |
/* ------------------------------------------------------------ */ |
||
103 |
|||
104 |
/* learned: if you copy/paste the macros for these kernels into |
||
105 |
** other code, you *have* to make sure that the arguments for the |
||
106 |
** kernels that are supposed to be reals, are not passed as an |
||
107 |
** integral type (had this problem trying to re-use _BCCUBIC |
||
108 |
** with constant B="1" and C="0" and had trouble figuring out |
||
109 |
** why the kernel was give garbage results |
||
110 |
*/ |
||
111 |
|||
112 |
/* the "zero" kernel is here more as a template than for anything else |
||
113 |
(as well as when you need the derivative of nrrdKernelForwDiff or |
||
114 |
any other piece-wise constant kernels) |
||
115 |
In particular the support method is pretty silly. */ |
||
116 |
|||
117 |
#define _ZERO(x) 0 |
||
118 |
|||
119 |
static double |
||
120 |
_nrrdZeroSup(const double *parm) { |
||
121 |
double S; |
||
122 |
|||
123 |
68 |
S = parm[0]; |
|
124 |
34 |
return S; |
|
125 |
} |
||
126 |
|||
127 |
static double |
||
128 |
_nrrdZero1_d(double x, const double *parm) { |
||
129 |
double S; |
||
130 |
|||
131 |
480024 |
S = parm[0]; |
|
132 |
240012 |
x = AIR_ABS(x)/S; |
|
133 |
240012 |
return _ZERO(x)/S; |
|
134 |
} |
||
135 |
|||
136 |
static float |
||
137 |
_nrrdZero1_f(float x, const double *parm) { |
||
138 |
float S; |
||
139 |
|||
140 |
480000 |
S = AIR_CAST(float, parm[0]); |
|
141 |
240000 |
x = AIR_ABS(x)/S; |
|
142 |
240000 |
return _ZERO(x)/S; |
|
143 |
} |
||
144 |
|||
145 |
static void |
||
146 |
_nrrdZeroN_d(double *f, const double *x, size_t len, const double *parm) { |
||
147 |
double S; |
||
148 |
double t; |
||
149 |
size_t i; |
||
150 |
|||
151 |
129460 |
S = parm[0]; |
|
152 |
✓✓ | 1386196 |
for (i=0; i<len; i++) { |
153 |
628368 |
t = x[i]; t = AIR_ABS(t)/S; |
|
154 |
628368 |
f[i] = _ZERO(t)/S; |
|
155 |
} |
||
156 |
64730 |
} |
|
157 |
|||
158 |
static void |
||
159 |
_nrrdZeroN_f(float *f, const float *x, size_t len, const double *parm) { |
||
160 |
float t, S; |
||
161 |
size_t i; |
||
162 |
|||
163 |
4 |
S = AIR_CAST(float, parm[0]); |
|
164 |
✓✓ | 480004 |
for (i=0; i<len; i++) { |
165 |
240000 |
t = x[i]; t = AIR_ABS(t)/S; |
|
166 |
240000 |
f[i] = _ZERO(t)/S; |
|
167 |
} |
||
168 |
2 |
} |
|
169 |
|||
170 |
static NrrdKernel |
||
171 |
_nrrdKernelZero = { |
||
172 |
"zero", |
||
173 |
1, _nrrdZeroSup, returnZero, |
||
174 |
_nrrdZero1_f, _nrrdZeroN_f, _nrrdZero1_d, _nrrdZeroN_d |
||
175 |
}; |
||
176 |
NrrdKernel *const |
||
177 |
nrrdKernelZero = &_nrrdKernelZero; |
||
178 |
|||
179 |
/* ------------------------------------------------------------ */ |
||
180 |
|||
181 |
#define _BOX(x) (x > 0.5 ? 0 : (x < 0.5 ? 1 : 0.5)) |
||
182 |
|||
183 |
static double |
||
184 |
_nrrdBoxSup(const double *parm) { |
||
185 |
double S; |
||
186 |
|||
187 |
8 |
S = parm[0]; |
|
188 |
/* adding the 0.5 is to ensure that weights computed within the |
||
189 |
support really do catch all the non-zero values */ |
||
190 |
4 |
return S/2 + 0.5; |
|
191 |
} |
||
192 |
|||
193 |
static double |
||
194 |
_nrrdBox1_d(double x, const double *parm) { |
||
195 |
double S; |
||
196 |
|||
197 |
480024 |
S = parm[0]; |
|
198 |
240012 |
x = AIR_ABS(x)/S; |
|
199 |
✓✓ | 624024 |
return _BOX(x)/S; |
200 |
} |
||
201 |
|||
202 |
static float |
||
203 |
_nrrdBox1_f(float x, const double *parm) { |
||
204 |
float S; |
||
205 |
|||
206 |
480000 |
S = AIR_CAST(float, parm[0]); |
|
207 |
240000 |
x = AIR_ABS(x)/S; |
|
208 |
✓✓ | 624000 |
return AIR_CAST(float, _BOX(x)/S); |
209 |
} |
||
210 |
|||
211 |
static void |
||
212 |
_nrrdBoxN_d(double *f, const double *x, size_t len, const double *parm) { |
||
213 |
double S; |
||
214 |
double t; |
||
215 |
size_t i; |
||
216 |
|||
217 |
6 |
S = parm[0]; |
|
218 |
✓✓ | 480018 |
for (i=0; i<len; i++) { |
219 |
240006 |
t = x[i]; t = AIR_ABS(t)/S; |
|
220 |
✓✓ | 624015 |
f[i] = _BOX(t)/S; |
221 |
} |
||
222 |
3 |
} |
|
223 |
|||
224 |
static void |
||
225 |
_nrrdBoxN_f(float *f, const float *x, size_t len, const double *parm) { |
||
226 |
float t, S; |
||
227 |
size_t i; |
||
228 |
|||
229 |
4 |
S = AIR_CAST(float, parm[0]); |
|
230 |
✓✓ | 480004 |
for (i=0; i<len; i++) { |
231 |
240000 |
t = x[i]; t = AIR_ABS(t)/S; |
|
232 |
✓✓ | 624000 |
f[i] = AIR_CAST(float, _BOX(t)/S); |
233 |
} |
||
234 |
2 |
} |
|
235 |
|||
236 |
static NrrdKernel |
||
237 |
_nrrdKernelBox = { |
||
238 |
"box", |
||
239 |
1, _nrrdBoxSup, returnOne, |
||
240 |
_nrrdBox1_f, _nrrdBoxN_f, _nrrdBox1_d, _nrrdBoxN_d |
||
241 |
}; |
||
242 |
NrrdKernel *const |
||
243 |
nrrdKernelBox = &_nrrdKernelBox; |
||
244 |
|||
245 |
/* ------------------------------------------------------------ */ |
||
246 |
|||
247 |
static double |
||
248 |
_nrrdBoxSDSup(const double *parm) { |
||
249 |
|||
250 |
76 |
return parm[0]; |
|
251 |
} |
||
252 |
|||
253 |
static double |
||
254 |
_nrrdBoxSD1_d(double x, const double *parm) { |
||
255 |
AIR_UNUSED(parm); |
||
256 |
480024 |
x = AIR_ABS(x); |
|
257 |
✓✓ | 565738 |
return _BOX(x); |
258 |
} |
||
259 |
|||
260 |
static float |
||
261 |
_nrrdBoxSD1_f(float x, const double *parm) { |
||
262 |
AIR_UNUSED(parm); |
||
263 |
480000 |
x = AIR_ABS(x); |
|
264 |
✓✓ | 565714 |
return AIR_CAST(float, _BOX(x)); |
265 |
} |
||
266 |
|||
267 |
static void |
||
268 |
_nrrdBoxSDN_d(double *f, const double *x, size_t len, const double *parm) { |
||
269 |
size_t i; |
||
270 |
AIR_UNUSED(parm); |
||
271 |
✓✓ | 1410546 |
for (i=0; i<len; i++) { |
272 |
double t; |
||
273 |
642780 |
t = AIR_ABS(x[i]); |
|
274 |
✓✓ | 1496614 |
f[i] = _BOX(t); |
275 |
} |
||
276 |
41662 |
} |
|
277 |
|||
278 |
static void |
||
279 |
_nrrdBoxSDN_f(float *f, const float *x, size_t len, const double *parm) { |
||
280 |
size_t i; |
||
281 |
AIR_UNUSED(parm); |
||
282 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
283 |
float t; |
||
284 |
240000 |
t = AIR_ABS(x[i]); |
|
285 |
✓✓ | 565714 |
f[i] = AIR_CAST(float, _BOX(t)); |
286 |
} |
||
287 |
2 |
} |
|
288 |
|||
289 |
static NrrdKernel |
||
290 |
_nrrdKernelBoxSupportDebug = { |
||
291 |
"boxsup", |
||
292 |
1, _nrrdBoxSDSup, returnOne, |
||
293 |
_nrrdBoxSD1_f, _nrrdBoxSDN_f, _nrrdBoxSD1_d, _nrrdBoxSDN_d |
||
294 |
}; |
||
295 |
NrrdKernel *const |
||
296 |
nrrdKernelBoxSupportDebug = &_nrrdKernelBoxSupportDebug; |
||
297 |
|||
298 |
/* ------------------------------------------------------------ */ |
||
299 |
|||
300 |
#define COS4(x) (x > 0.5 \ |
||
301 |
? 0.0 \ |
||
302 |
: cos(AIR_PI*x)*cos(AIR_PI*x)*cos(AIR_PI*x)*cos(AIR_PI*x)) |
||
303 |
|||
304 |
static double |
||
305 |
_nrrdCos4SDInt(const double *parm) { |
||
306 |
AIR_UNUSED(parm); |
||
307 |
108 |
return 3.0/8.0; |
|
308 |
} |
||
309 |
|||
310 |
static double |
||
311 |
_nrrdCos4SDSup(const double *parm) { |
||
312 |
|||
313 |
212 |
return parm[0]; |
|
314 |
} |
||
315 |
|||
316 |
static double |
||
317 |
_nrrdCos4SD1_d(double x, const double *parm) { |
||
318 |
AIR_UNUSED(parm); |
||
319 |
1440024 |
x = AIR_ABS(x); |
|
320 |
✓✓ | 1697170 |
return COS4(x); |
321 |
} |
||
322 |
|||
323 |
static float |
||
324 |
_nrrdCos4SD1_f(float x, const double *parm) { |
||
325 |
AIR_UNUSED(parm); |
||
326 |
480000 |
x = AIR_ABS(x); |
|
327 |
✓✓ | 565714 |
return AIR_CAST(float, COS4(x)); |
328 |
} |
||
329 |
|||
330 |
static void |
||
331 |
_nrrdCos4SDN_d(double *f, const double *x, size_t len, const double *parm) { |
||
332 |
size_t i; |
||
333 |
AIR_UNUSED(parm); |
||
334 |
✓✓ | 4016946 |
for (i=0; i<len; i++) { |
335 |
double t; |
||
336 |
1837980 |
t = AIR_ABS(x[i]); |
|
337 |
✓✓ | 4103014 |
f[i] = COS4(t); |
338 |
} |
||
339 |
113662 |
} |
|
340 |
|||
341 |
static void |
||
342 |
_nrrdCos4SDN_f(float *f, const float *x, size_t len, const double *parm) { |
||
343 |
size_t i; |
||
344 |
AIR_UNUSED(parm); |
||
345 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
346 |
float t; |
||
347 |
240000 |
t = AIR_ABS(x[i]); |
|
348 |
✓✓ | 565714 |
f[i] = AIR_CAST(float, COS4(t)); |
349 |
} |
||
350 |
2 |
} |
|
351 |
|||
352 |
static NrrdKernel |
||
353 |
_nrrdKernelCos4SupportDebug = { |
||
354 |
"cos4sup", |
||
355 |
1, _nrrdCos4SDSup, _nrrdCos4SDInt, |
||
356 |
_nrrdCos4SD1_f, _nrrdCos4SDN_f, _nrrdCos4SD1_d, _nrrdCos4SDN_d |
||
357 |
}; |
||
358 |
NrrdKernel *const |
||
359 |
nrrdKernelCos4SupportDebug = &_nrrdKernelCos4SupportDebug; |
||
360 |
|||
361 |
/* ------------------------------------------------------------ */ |
||
362 |
|||
363 |
#define DCOS4(x) (x > 0.5 \ |
||
364 |
? 0.0 \ |
||
365 |
: -4*AIR_PI*(cos(AIR_PI*x)*cos(AIR_PI*x)*cos(AIR_PI*x) \ |
||
366 |
*sin(AIR_PI*x))) |
||
367 |
|||
368 |
static double |
||
369 |
_nrrdDCos4SDSup(const double *parm) { |
||
370 |
204 |
return parm[0]; |
|
371 |
} |
||
372 |
|||
373 |
static double |
||
374 |
_nrrdDCos4SD1_d(double x, const double *parm) { |
||
375 |
int sgn; |
||
376 |
AIR_UNUSED(parm); |
||
377 |
✓✓ | 1800029 |
if (x < 0) { x = -x; sgn = -1; } else { sgn = 1; } |
378 |
✓✓ | 1697170 |
return sgn*DCOS4(x); |
379 |
} |
||
380 |
|||
381 |
static float |
||
382 |
_nrrdDCos4SD1_f(float x, const double *parm) { |
||
383 |
int sgn; |
||
384 |
AIR_UNUSED(parm); |
||
385 |
✓✓ | 600000 |
if (x < 0) { x = -x; sgn = -1; } else { sgn = 1; } |
386 |
✓✓ | 565714 |
return AIR_CAST(float, sgn*DCOS4(x)); |
387 |
} |
||
388 |
|||
389 |
static void |
||
390 |
_nrrdDCos4SDN_d(double *f, const double *x, size_t len, const double *parm) { |
||
391 |
int sgn; |
||
392 |
double t; |
||
393 |
size_t i; |
||
394 |
AIR_UNUSED(parm); |
||
395 |
✓✓ | 3432846 |
for (i=0; i<len; i++) { |
396 |
1566180 |
t = x[i]; |
|
397 |
✓✓ | 2349270 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
398 |
✓✓ | 3518914 |
f[i] = sgn*DCOS4(t); |
399 |
} |
||
400 |
100162 |
} |
|
401 |
|||
402 |
static void |
||
403 |
_nrrdDCos4SDN_f(float *f, const float *x, size_t len, const double *parm) { |
||
404 |
int sgn; |
||
405 |
float t; |
||
406 |
size_t i; |
||
407 |
AIR_UNUSED(parm); |
||
408 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
409 |
240000 |
t = x[i]; |
|
410 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
411 |
✓✓ | 565714 |
f[i] = AIR_CAST(float, sgn*DCOS4(t)); |
412 |
} |
||
413 |
2 |
} |
|
414 |
|||
415 |
static NrrdKernel |
||
416 |
_nrrdKernelCos4SupportDebugD = { |
||
417 |
"cos4supD", |
||
418 |
1, _nrrdDCos4SDSup, returnZero, |
||
419 |
_nrrdDCos4SD1_f, _nrrdDCos4SDN_f, _nrrdDCos4SD1_d, _nrrdDCos4SDN_d |
||
420 |
}; |
||
421 |
NrrdKernel *const |
||
422 |
nrrdKernelCos4SupportDebugD = &_nrrdKernelCos4SupportDebugD; |
||
423 |
|||
424 |
/* ------------------------------------------------------------ */ |
||
425 |
|||
426 |
#define DDCOS4(x) (x > 0.5 \ |
||
427 |
? 0.0 \ |
||
428 |
: -2*AIR_PI*AIR_PI*(cos(AIR_PI*2*x) + cos(AIR_PI*4*x))) |
||
429 |
|||
430 |
static double |
||
431 |
_nrrdDDCos4SDSup(const double *parm) { |
||
432 |
204 |
return parm[0]; |
|
433 |
} |
||
434 |
|||
435 |
static double |
||
436 |
_nrrdDDCos4SD1_d(double x, const double *parm) { |
||
437 |
AIR_UNUSED(parm); |
||
438 |
1440024 |
x = AIR_ABS(x); |
|
439 |
✓✓ | 1697170 |
return DDCOS4(x); |
440 |
} |
||
441 |
|||
442 |
static float |
||
443 |
_nrrdDDCos4SD1_f(float x, const double *parm) { |
||
444 |
AIR_UNUSED(parm); |
||
445 |
480000 |
x = AIR_ABS(x); |
|
446 |
✓✓ | 565714 |
return AIR_CAST(float, DDCOS4(x)); |
447 |
} |
||
448 |
|||
449 |
static void |
||
450 |
_nrrdDDCos4SDN_d(double *f, const double *x, size_t len, const double *parm) { |
||
451 |
size_t i; |
||
452 |
AIR_UNUSED(parm); |
||
453 |
✓✓ | 3432846 |
for (i=0; i<len; i++) { |
454 |
double t; |
||
455 |
1566180 |
t = AIR_ABS(x[i]); |
|
456 |
✓✓ | 3518914 |
f[i] = DDCOS4(t); |
457 |
} |
||
458 |
100162 |
} |
|
459 |
|||
460 |
static void |
||
461 |
_nrrdDDCos4SDN_f(float *f, const float *x, size_t len, const double *parm) { |
||
462 |
size_t i; |
||
463 |
AIR_UNUSED(parm); |
||
464 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
465 |
float t; |
||
466 |
240000 |
t = AIR_ABS(x[i]); |
|
467 |
✓✓ | 565714 |
f[i] = AIR_CAST(float, DDCOS4(t)); |
468 |
} |
||
469 |
2 |
} |
|
470 |
|||
471 |
static NrrdKernel |
||
472 |
_nrrdKernelCos4SupportDebugDD = { |
||
473 |
"cos4supDD", |
||
474 |
1, _nrrdDDCos4SDSup, returnZero, |
||
475 |
_nrrdDDCos4SD1_f, _nrrdDDCos4SDN_f, _nrrdDDCos4SD1_d, _nrrdDDCos4SDN_d |
||
476 |
}; |
||
477 |
NrrdKernel *const |
||
478 |
nrrdKernelCos4SupportDebugDD = &_nrrdKernelCos4SupportDebugDD; |
||
479 |
|||
480 |
/* ------------------------------------------------------------ */ |
||
481 |
|||
482 |
#define DDDCOS4(x) (x > 0.5 \ |
||
483 |
? 0.0 \ |
||
484 |
: 4*AIR_PI*AIR_PI*AIR_PI*(sin(2*AIR_PI*x) + 2*sin(4*AIR_PI*x))) |
||
485 |
|||
486 |
static double |
||
487 |
_nrrdDDDCos4SDSup(const double *parm) { |
||
488 |
4 |
return parm[0]; |
|
489 |
} |
||
490 |
|||
491 |
static double |
||
492 |
_nrrdDDDCos4SD1_d(double x, const double *parm) { |
||
493 |
int sgn; |
||
494 |
AIR_UNUSED(parm); |
||
495 |
✓✓ | 600030 |
if (x < 0) { x = -x; sgn = -1; } else { sgn = 1; } |
496 |
✓✓ | 565738 |
return sgn*DDDCOS4(x); |
497 |
} |
||
498 |
|||
499 |
static float |
||
500 |
_nrrdDDDCos4SD1_f(float x, const double *parm) { |
||
501 |
int sgn; |
||
502 |
AIR_UNUSED(parm); |
||
503 |
✓✓ | 600000 |
if (x < 0) { x = -x; sgn = -1; } else { sgn = 1; } |
504 |
✓✓ | 565714 |
return AIR_CAST(float, sgn*DDDCOS4(x)); |
505 |
} |
||
506 |
|||
507 |
static void |
||
508 |
_nrrdDDDCos4SDN_d(double *f, const double *x, size_t len, const double *parm) { |
||
509 |
int sgn; |
||
510 |
double t; |
||
511 |
size_t i; |
||
512 |
AIR_UNUSED(parm); |
||
513 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
514 |
240000 |
t = x[i]; |
|
515 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
516 |
✓✓ | 565714 |
f[i] = sgn*DDDCOS4(t); |
517 |
} |
||
518 |
2 |
} |
|
519 |
|||
520 |
static void |
||
521 |
_nrrdDDDCos4SDN_f(float *f, const float *x, size_t len, const double *parm) { |
||
522 |
int sgn; |
||
523 |
float t; |
||
524 |
size_t i; |
||
525 |
AIR_UNUSED(parm); |
||
526 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
527 |
240000 |
t = x[i]; |
|
528 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
529 |
✓✓ | 565714 |
f[i] = AIR_CAST(float, sgn*DDDCOS4(t)); |
530 |
} |
||
531 |
2 |
} |
|
532 |
|||
533 |
static NrrdKernel |
||
534 |
_nrrdKernelCos4SupportDebugDDD = { |
||
535 |
"cos4supDDD", |
||
536 |
1, _nrrdDDDCos4SDSup, returnZero, |
||
537 |
_nrrdDDDCos4SD1_f, _nrrdDDDCos4SDN_f, _nrrdDDDCos4SD1_d, _nrrdDDDCos4SDN_d |
||
538 |
}; |
||
539 |
NrrdKernel *const |
||
540 |
nrrdKernelCos4SupportDebugDDD = &_nrrdKernelCos4SupportDebugDDD; |
||
541 |
|||
542 |
/* ------------------------------------------------------------ */ |
||
543 |
|||
544 |
/* The point here is that post-kernel-evaluation, we need to see |
||
545 |
which sample is closest to the origin, and this is one way of |
||
546 |
enabling that |
||
547 |
SO: this kernel will not usefully report its integral or support! */ |
||
548 |
#define _CHEAP(x) AIR_ABS(x) |
||
549 |
|||
550 |
static double |
||
551 |
_nrrdCheapSup(const double *parm) { |
||
552 |
double S; |
||
553 |
|||
554 |
4 |
S = parm[0]; |
|
555 |
/* adding the 0.5 is to insure that weights computed within the |
||
556 |
support really do catch all the non-zero values */ |
||
557 |
2 |
return S/2 + 0.5; |
|
558 |
} |
||
559 |
|||
560 |
static double |
||
561 |
_nrrdCheap1_d(double x, const double *parm) { |
||
562 |
|||
563 |
480004 |
return _CHEAP(x)/parm[0]; |
|
564 |
} |
||
565 |
|||
566 |
static float |
||
567 |
_nrrdCheap1_f(float x, const double *parm) { |
||
568 |
|||
569 |
480000 |
return AIR_CAST(float, _CHEAP(x)/parm[0]); |
|
570 |
} |
||
571 |
|||
572 |
static void |
||
573 |
_nrrdCheapN_d(double *f, const double *x, size_t len, const double *parm) { |
||
574 |
double t; |
||
575 |
size_t i; |
||
576 |
|||
577 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
578 |
240000 |
t = x[i]; |
|
579 |
240000 |
f[i] = _CHEAP(t)/parm[0]; |
|
580 |
} |
||
581 |
2 |
} |
|
582 |
|||
583 |
static void |
||
584 |
_nrrdCheapN_f(float *f, const float *x, size_t len, const double *parm) { |
||
585 |
float t; |
||
586 |
size_t i; |
||
587 |
|||
588 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
589 |
240000 |
t = x[i]; |
|
590 |
240000 |
f[i] = AIR_CAST(float, _CHEAP(t)/parm[0]); |
|
591 |
} |
||
592 |
2 |
} |
|
593 |
|||
594 |
static NrrdKernel |
||
595 |
_nrrdKernelCheap = { |
||
596 |
"cheap", |
||
597 |
1, _nrrdCheapSup, returnOne, |
||
598 |
_nrrdCheap1_f, _nrrdCheapN_f, _nrrdCheap1_d, _nrrdCheapN_d |
||
599 |
}; |
||
600 |
NrrdKernel *const |
||
601 |
nrrdKernelCheap = &_nrrdKernelCheap; |
||
602 |
|||
603 |
/* ------------------------------------------------------------ */ |
||
604 |
|||
605 |
#define _TENT(x) (x >= 1 ? 0 : 1 - x) |
||
606 |
|||
607 |
static double |
||
608 |
_nrrdTentSup(const double *parm) { |
||
609 |
double S; |
||
610 |
|||
611 |
12 |
S = parm[0]; |
|
612 |
6 |
return S; |
|
613 |
} |
||
614 |
|||
615 |
static double |
||
616 |
_nrrdTent1_d(double x, const double *parm) { |
||
617 |
double S; |
||
618 |
|||
619 |
480024 |
S = parm[0]; |
|
620 |
240012 |
x = AIR_ABS(x)/S; |
|
621 |
✓✗ | 720036 |
return S ? _TENT(x)/S : x == 0; |
622 |
} |
||
623 |
|||
624 |
static float |
||
625 |
_nrrdTent1_f(float x, const double *parm) { |
||
626 |
float S; |
||
627 |
|||
628 |
480000 |
S = AIR_CAST(float, parm[0]); |
|
629 |
240000 |
x = AIR_ABS(x)/S; |
|
630 |
✓✗ | 720000 |
return S ? _TENT(x)/S : x == 0; |
631 |
} |
||
632 |
|||
633 |
static void |
||
634 |
_nrrdTentN_d(double *f, const double *x, size_t len, const double *parm) { |
||
635 |
double S; |
||
636 |
double t; |
||
637 |
size_t i; |
||
638 |
|||
639 |
3462 |
S = parm[0]; |
|
640 |
✓✓ | 504210 |
for (i=0; i<len; i++) { |
641 |
250374 |
t = x[i]; t = AIR_ABS(t)/S; |
|
642 |
✓✗ | 751122 |
f[i] = S ? _TENT(t)/S : t == 0; |
643 |
} |
||
644 |
1731 |
} |
|
645 |
|||
646 |
static void |
||
647 |
_nrrdTentN_f(float *f, const float *x, size_t len, const double *parm) { |
||
648 |
float t, S; |
||
649 |
size_t i; |
||
650 |
|||
651 |
4 |
S = AIR_CAST(float, parm[0]); |
|
652 |
✓✓ | 480004 |
for (i=0; i<len; i++) { |
653 |
240000 |
t = x[i]; t = AIR_ABS(t)/S; |
|
654 |
✓✗ | 720000 |
f[i] = S ? _TENT(t)/S : t == 0; |
655 |
} |
||
656 |
2 |
} |
|
657 |
|||
658 |
static NrrdKernel |
||
659 |
_nrrdKernelTent = { |
||
660 |
"tent", |
||
661 |
1, _nrrdTentSup, returnOne, |
||
662 |
_nrrdTent1_f, _nrrdTentN_f, _nrrdTent1_d, _nrrdTentN_d |
||
663 |
}; |
||
664 |
NrrdKernel *const |
||
665 |
nrrdKernelTent = &_nrrdKernelTent; |
||
666 |
|||
667 |
/* ------------------------------------------------------------ */ |
||
668 |
|||
669 |
/* |
||
670 |
** NOTE: THERE IS NOT REALLY A HERMITE KERNEL (at least not yet, |
||
671 |
** because it takes both values and derivatives as arguments, which |
||
672 |
** the NrrdKernel currently can't handle). This isn't really a |
||
673 |
** kernel, its mostly a flag (hence the name), but it also has the |
||
674 |
** role of generating weights according to linear interpolation, which |
||
675 |
** is useful for the eventual spline evaluation. |
||
676 |
** |
||
677 |
** This hack is in sinister collusion with gage, to enable Hermite |
||
678 |
** interpolation for its stack reconstruction. |
||
679 |
*/ |
||
680 |
|||
681 |
static double |
||
682 |
_nrrdHermite1_d(double x, const double *parm) { |
||
683 |
AIR_UNUSED(parm); |
||
684 |
240012 |
x = AIR_ABS(x); |
|
685 |
120006 |
return _TENT(x); |
|
686 |
} |
||
687 |
|||
688 |
static float |
||
689 |
_nrrdHermite1_f(float x, const double *parm) { |
||
690 |
AIR_UNUSED(parm); |
||
691 |
240000 |
x = AIR_ABS(x); |
|
692 |
120000 |
return _TENT(x); |
|
693 |
} |
||
694 |
|||
695 |
static void |
||
696 |
_nrrdHermiteN_d(double *f, const double *x, size_t len, const double *parm) { |
||
697 |
double t; |
||
698 |
size_t i; |
||
699 |
AIR_UNUSED(parm); |
||
700 |
✓✓ | 240003 |
for (i=0; i<len; i++) { |
701 |
120000 |
t = x[i]; t = AIR_ABS(t); |
|
702 |
120000 |
f[i] = _TENT(t); |
|
703 |
} |
||
704 |
1 |
} |
|
705 |
|||
706 |
static void |
||
707 |
_nrrdHermiteN_f(float *f, const float *x, size_t len, const double *parm) { |
||
708 |
float t; |
||
709 |
size_t i; |
||
710 |
AIR_UNUSED(parm); |
||
711 |
✓✓ | 240003 |
for (i=0; i<len; i++) { |
712 |
120000 |
t = x[i]; t = AIR_ABS(t); |
|
713 |
120000 |
f[i] = _TENT(t); |
|
714 |
} |
||
715 |
1 |
} |
|
716 |
|||
717 |
/* HEY: should just re-use fields from nrrdKernelTent, instead |
||
718 |
of creating new functions */ |
||
719 |
static NrrdKernel |
||
720 |
_nrrdKernelHermiteScaleSpaceFlag = { |
||
721 |
"hermiteSS", |
||
722 |
0, returnOne, returnOne, |
||
723 |
_nrrdHermite1_f, _nrrdHermiteN_f, _nrrdHermite1_d, _nrrdHermiteN_d |
||
724 |
}; |
||
725 |
NrrdKernel *const |
||
726 |
nrrdKernelHermiteScaleSpaceFlag = &_nrrdKernelHermiteScaleSpaceFlag; |
||
727 |
|||
728 |
/* ------------------------------------------------------------ */ |
||
729 |
|||
730 |
#define _FORDIF(x) (x < -1 ? 0.0f : \ |
||
731 |
(x < 0 ? 1.0f : \ |
||
732 |
(x < 1 ? -1.0f : 0.0f ))) |
||
733 |
|||
734 |
static double |
||
735 |
_nrrdFDSup(const double *parm) { |
||
736 |
double S; |
||
737 |
|||
738 |
8 |
S = parm[0]; |
|
739 |
4 |
return S+0.0001; /* sigh */ |
|
740 |
} |
||
741 |
|||
742 |
static double |
||
743 |
_nrrdFD1_d(double x, const double *parm) { |
||
744 |
double t, S; |
||
745 |
|||
746 |
480024 |
S = parm[0]; |
|
747 |
240012 |
t = x/S; |
|
748 |
✓✓✓✓ |
840027 |
return _FORDIF(t)/(S*S); |
749 |
} |
||
750 |
|||
751 |
static float |
||
752 |
_nrrdFD1_f(float x, const double *parm) { |
||
753 |
float t, S; |
||
754 |
|||
755 |
480000 |
S = AIR_CAST(float, parm[0]); |
|
756 |
240000 |
t = x/S; |
|
757 |
✓✓✓✓ |
839991 |
return _FORDIF(t)/(S*S); |
758 |
} |
||
759 |
|||
760 |
static void |
||
761 |
_nrrdFDN_d(double *f, const double *x, size_t len, const double *parm) { |
||
762 |
double t, S; |
||
763 |
size_t i; |
||
764 |
|||
765 |
3460 |
S = parm[0]; |
|
766 |
✓✓ | 504196 |
for (i=0; i<len; i++) { |
767 |
250368 |
t = x[i]/S; |
|
768 |
✓✓✓✓ |
876279 |
f[i] = _FORDIF(t)/(S*S); |
769 |
} |
||
770 |
1730 |
} |
|
771 |
|||
772 |
static void |
||
773 |
_nrrdFDN_f(float *f, const float *x, size_t len, const double *parm) { |
||
774 |
float t, S; |
||
775 |
size_t i; |
||
776 |
|||
777 |
4 |
S = AIR_CAST(float, parm[0]); |
|
778 |
✓✓ | 480004 |
for (i=0; i<len; i++) { |
779 |
240000 |
t = x[i]/S; |
|
780 |
✓✓✓✓ |
839991 |
f[i] = _FORDIF(t)/(S*S); |
781 |
} |
||
782 |
2 |
} |
|
783 |
|||
784 |
static NrrdKernel |
||
785 |
_nrrdKernelFD = { |
||
786 |
"fordif", |
||
787 |
1, _nrrdFDSup, returnZero, |
||
788 |
_nrrdFD1_f, _nrrdFDN_f, _nrrdFD1_d, _nrrdFDN_d |
||
789 |
}; |
||
790 |
NrrdKernel *const |
||
791 |
nrrdKernelForwDiff = &_nrrdKernelFD; |
||
792 |
|||
793 |
/* ------------------------------------------------------------ */ |
||
794 |
|||
795 |
#define _CENDIF(x) (x <= -2 ? 0 : \ |
||
796 |
(x <= -1 ? 0.5*x + 1 : \ |
||
797 |
(x <= 1 ? -0.5*x : \ |
||
798 |
(x <= 2 ? 0.5*x - 1 : 0 )))) |
||
799 |
|||
800 |
static double |
||
801 |
_nrrdCDSup(const double *parm) { |
||
802 |
double S; |
||
803 |
|||
804 |
4 |
S = parm[0]; |
|
805 |
2 |
return 2*S; |
|
806 |
} |
||
807 |
|||
808 |
static double |
||
809 |
_nrrdCD1_d(double x, const double *parm) { |
||
810 |
double S; |
||
811 |
|||
812 |
480024 |
S = parm[0]; |
|
813 |
240012 |
x /= S; |
|
814 |
✓✓✓✓ ✓✓✓✓ |
1200042 |
return _CENDIF(x)/(S*S); |
815 |
} |
||
816 |
|||
817 |
static float |
||
818 |
_nrrdCD1_f(float x, const double *parm) { |
||
819 |
float S; |
||
820 |
|||
821 |
480000 |
S = AIR_CAST(float, parm[0]); |
|
822 |
240000 |
x /= S; |
|
823 |
✓✗✓✓ ✓✓✓✗ |
1200000 |
return AIR_CAST(float, _CENDIF(x)/(S*S)); |
824 |
} |
||
825 |
|||
826 |
static void |
||
827 |
_nrrdCDN_d(double *f, const double *x, size_t len, const double *parm) { |
||
828 |
double S; |
||
829 |
double t; |
||
830 |
size_t i; |
||
831 |
|||
832 |
4 |
S = parm[0]; |
|
833 |
✓✓ | 480004 |
for (i=0; i<len; i++) { |
834 |
240000 |
t = x[i]/S; |
|
835 |
✓✗✓✓ ✓✓✓✗ |
1200000 |
f[i] = _CENDIF(t)/(S*S); |
836 |
} |
||
837 |
2 |
} |
|
838 |
|||
839 |
static void |
||
840 |
_nrrdCDN_f(float *f, const float *x, size_t len, const double *parm) { |
||
841 |
float t, S; |
||
842 |
size_t i; |
||
843 |
|||
844 |
4 |
S = AIR_CAST(float, parm[0]); |
|
845 |
✓✓ | 480004 |
for (i=0; i<len; i++) { |
846 |
240000 |
t = x[i]/S; |
|
847 |
✓✗✓✓ ✓✓✓✗ |
1200000 |
f[i] = AIR_CAST(float, _CENDIF(t)/(S*S)); |
848 |
} |
||
849 |
2 |
} |
|
850 |
|||
851 |
static NrrdKernel |
||
852 |
_nrrdKernelCD = { |
||
853 |
"cendif", |
||
854 |
1, _nrrdCDSup, returnZero, |
||
855 |
_nrrdCD1_f, _nrrdCDN_f, _nrrdCD1_d, _nrrdCDN_d |
||
856 |
}; |
||
857 |
NrrdKernel *const |
||
858 |
nrrdKernelCentDiff = &_nrrdKernelCD; |
||
859 |
|||
860 |
/* ------------------------------------------------------------ */ |
||
861 |
|||
862 |
#define _BCCUBIC(x, B, C) \ |
||
863 |
(x >= 2.0 ? 0 : \ |
||
864 |
(x >= 1.0 \ |
||
865 |
? (((-B/6 - C)*x + B + 5*C)*x -2*B - 8*C)*x + 4*B/3 + 4*C \ |
||
866 |
: ((2 - 3*B/2 - C)*x - 3 + 2*B + C)*x*x + 1 - B/3)) |
||
867 |
|||
868 |
static double |
||
869 |
_nrrdBCSup(const double *parm) { |
||
870 |
double S; |
||
871 |
|||
872 |
24 |
S = parm[0]; |
|
873 |
12 |
return 2*S; |
|
874 |
} |
||
875 |
|||
876 |
static double |
||
877 |
_nrrdBC1_d(double x, const double *parm) { |
||
878 |
double S; |
||
879 |
double B, C; |
||
880 |
|||
881 |
5760096 |
S = parm[0]; B = parm[1]; C = parm[2]; |
|
882 |
2880048 |
x = AIR_ABS(x)/S; |
|
883 |
✓✓✓✓ |
11520064 |
return _BCCUBIC(x, B, C)/S; |
884 |
} |
||
885 |
|||
886 |
static float |
||
887 |
_nrrdBC1_f(float x, const double *parm) { |
||
888 |
float B, C, S; |
||
889 |
|||
890 |
1920000 |
S = AIR_CAST(float, parm[0]); |
|
891 |
960000 |
B = AIR_CAST(float, parm[1]); |
|
892 |
960000 |
C = AIR_CAST(float, parm[2]); |
|
893 |
960000 |
x = AIR_ABS(x)/S; |
|
894 |
✓✗✓✓ |
3840000 |
return _BCCUBIC(x, B, C)/S; |
895 |
} |
||
896 |
|||
897 |
static void |
||
898 |
_nrrdBCN_d(double *f, const double *x, size_t len, const double *parm) { |
||
899 |
double S; |
||
900 |
double t, B, C; |
||
901 |
size_t i; |
||
902 |
|||
903 |
3474 |
S = parm[0]; B = parm[1]; C = parm[2]; |
|
904 |
✓✓ | 2006442 |
for (i=0; i<len; i++) { |
905 |
1001484 |
t = x[i]; |
|
906 |
1001484 |
t = AIR_ABS(t)/S; |
|
907 |
✓✓✓✓ |
4004202 |
f[i] = _BCCUBIC(t, B, C)/S; |
908 |
} |
||
909 |
1737 |
} |
|
910 |
|||
911 |
static void |
||
912 |
_nrrdBCN_f(float *f, const float *x, size_t len, const double *parm) { |
||
913 |
float S, t, B, C; |
||
914 |
size_t i; |
||
915 |
|||
916 |
16 |
S = AIR_CAST(float, parm[0]); |
|
917 |
8 |
B = AIR_CAST(float, parm[1]); |
|
918 |
8 |
C = AIR_CAST(float, parm[2]); |
|
919 |
✓✓ | 1920016 |
for (i=0; i<len; i++) { |
920 |
960000 |
t = x[i]; |
|
921 |
960000 |
t = AIR_ABS(t)/S; |
|
922 |
✓✗✓✓ |
3840000 |
f[i] = _BCCUBIC(t, B, C)/S; |
923 |
} |
||
924 |
8 |
} |
|
925 |
|||
926 |
static NrrdKernel |
||
927 |
_nrrdKernelBC = { |
||
928 |
"BCcubic", |
||
929 |
3, _nrrdBCSup, returnOne, |
||
930 |
_nrrdBC1_f, _nrrdBCN_f, _nrrdBC1_d, _nrrdBCN_d |
||
931 |
}; |
||
932 |
NrrdKernel *const |
||
933 |
nrrdKernelBCCubic = &_nrrdKernelBC; |
||
934 |
|||
935 |
/* ------------------------------------------------------------ */ |
||
936 |
|||
937 |
#define _DBCCUBIC(x, B, C) \ |
||
938 |
(x >= 2.0 ? 0.0 : \ |
||
939 |
(x >= 1.0 \ |
||
940 |
? ((-B/2 - 3*C)*x + 2*B + 10*C)*x -2*B - 8*C \ |
||
941 |
: ((6 - 9*B/2 - 3*C)*x - 6 + 4*B + 2*C)*x)) |
||
942 |
|||
943 |
static double |
||
944 |
_nrrdDBCSup(const double *parm) { |
||
945 |
double S; |
||
946 |
|||
947 |
20 |
S = parm[0]; |
|
948 |
10 |
return 2*S; |
|
949 |
} |
||
950 |
|||
951 |
static double |
||
952 |
_nrrdDBC1_d(double x, const double *parm) { |
||
953 |
double S; |
||
954 |
double B, C; |
||
955 |
int sgn = 1; |
||
956 |
|||
957 |
5760096 |
S = parm[0]; B = parm[1]; C = parm[2]; |
|
958 |
✓✓ | 4320068 |
if (x < 0) { x = -x; sgn = -1; } |
959 |
2880048 |
x /= S; |
|
960 |
✓✓✓✓ |
11520064 |
return sgn*_DBCCUBIC(x, B, C)/(S*S); |
961 |
} |
||
962 |
|||
963 |
static float |
||
964 |
_nrrdDBC1_f(float x, const double *parm) { |
||
965 |
float B, C, S; |
||
966 |
int sgn = 1; |
||
967 |
|||
968 |
1920000 |
S = AIR_CAST(float, parm[0]); |
|
969 |
960000 |
B = AIR_CAST(float, parm[1]); |
|
970 |
960000 |
C = AIR_CAST(float, parm[2]); |
|
971 |
✓✓ | 1440000 |
if (x < 0) { x = -x; sgn = -1; } |
972 |
960000 |
x /= S; |
|
973 |
✓✗✓✓ |
4800000 |
return AIR_CAST(float, sgn*_DBCCUBIC(x, B, C)/(S*S)); |
974 |
} |
||
975 |
|||
976 |
static void |
||
977 |
_nrrdDBCN_d(double *f, const double *x, size_t len, const double *parm) { |
||
978 |
double S; |
||
979 |
double t, B, C; |
||
980 |
size_t i; |
||
981 |
int sgn; |
||
982 |
|||
983 |
3472 |
S = parm[0]; B = parm[1]; C = parm[2]; |
|
984 |
✓✓ | 2006416 |
for (i=0; i<len; i++) { |
985 |
1001472 |
t = x[i]/S; |
|
986 |
✓✓ | 1502208 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
987 |
✓✓✓✓ |
4004160 |
f[i] = sgn*_DBCCUBIC(t, B, C)/(S*S); |
988 |
} |
||
989 |
1736 |
} |
|
990 |
|||
991 |
static void |
||
992 |
_nrrdDBCN_f(float *f, const float *x, size_t len, const double *parm) { |
||
993 |
float S, t, B, C; |
||
994 |
int sgn; |
||
995 |
size_t i; |
||
996 |
|||
997 |
16 |
S = AIR_CAST(float, parm[0]); |
|
998 |
8 |
B = AIR_CAST(float, parm[1]); |
|
999 |
8 |
C = AIR_CAST(float, parm[2]); |
|
1000 |
✓✓ | 1920016 |
for (i=0; i<len; i++) { |
1001 |
960000 |
t = x[i]/S; |
|
1002 |
✓✓ | 1440000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1003 |
✓✗✓✓ |
4800000 |
f[i] = AIR_CAST(float, sgn*_DBCCUBIC(t, B, C)/(S*S)); |
1004 |
} |
||
1005 |
8 |
} |
|
1006 |
|||
1007 |
static NrrdKernel |
||
1008 |
_nrrdKernelDBC = { |
||
1009 |
"BCcubicD", |
||
1010 |
3, _nrrdDBCSup, returnZero, |
||
1011 |
_nrrdDBC1_f, _nrrdDBCN_f, _nrrdDBC1_d, _nrrdDBCN_d |
||
1012 |
}; |
||
1013 |
NrrdKernel *const |
||
1014 |
nrrdKernelBCCubicD = &_nrrdKernelDBC; |
||
1015 |
|||
1016 |
/* ------------------------------------------------------------ */ |
||
1017 |
|||
1018 |
#define _DDBCCUBIC(x, B, C) \ |
||
1019 |
(x >= 2.0 ? 0 : \ |
||
1020 |
(x >= 1.0 \ |
||
1021 |
? (-B - 6*C)*x + 2*B + 10*C \ |
||
1022 |
: (12 - 9*B - 6*C)*x - 6 + 4*B + 2*C )) |
||
1023 |
|||
1024 |
static double |
||
1025 |
_nrrdDDBCSup(const double *parm) { |
||
1026 |
double S; |
||
1027 |
|||
1028 |
20 |
S = parm[0]; |
|
1029 |
10 |
return 2*S; |
|
1030 |
} |
||
1031 |
|||
1032 |
static double |
||
1033 |
_nrrdDDBC1_d(double x, const double *parm) { |
||
1034 |
double S; |
||
1035 |
double B, C; |
||
1036 |
|||
1037 |
1920096 |
S = parm[0]; B = parm[1]; C = parm[2]; |
|
1038 |
960048 |
x = AIR_ABS(x)/S; |
|
1039 |
✓✓✓✓ |
3840096 |
return _DDBCCUBIC(x, B, C)/(S*S*S); |
1040 |
} |
||
1041 |
|||
1042 |
static float |
||
1043 |
_nrrdDDBC1_f(float x, const double *parm) { |
||
1044 |
float B, C, S; |
||
1045 |
|||
1046 |
1920000 |
S = AIR_CAST(float, parm[0]); |
|
1047 |
960000 |
B = AIR_CAST(float, parm[1]); |
|
1048 |
960000 |
C = AIR_CAST(float, parm[2]); |
|
1049 |
960000 |
x = AIR_ABS(x)/S; |
|
1050 |
✓✗✓✓ |
3840000 |
return _DDBCCUBIC(x, B, C)/(S*S*S); |
1051 |
} |
||
1052 |
|||
1053 |
static void |
||
1054 |
_nrrdDDBCN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1055 |
double S; |
||
1056 |
double t, B, C; |
||
1057 |
size_t i; |
||
1058 |
|||
1059 |
3472 |
S = parm[0]; B = parm[1]; C = parm[2]; |
|
1060 |
✓✓ | 2006416 |
for (i=0; i<len; i++) { |
1061 |
1001472 |
t = x[i]; |
|
1062 |
1001472 |
t = AIR_ABS(t)/S; |
|
1063 |
✓✓✓✓ |
4004160 |
f[i] = _DDBCCUBIC(t, B, C)/(S*S*S); |
1064 |
} |
||
1065 |
1736 |
} |
|
1066 |
|||
1067 |
static void |
||
1068 |
_nrrdDDBCN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1069 |
float S, t, B, C; |
||
1070 |
size_t i; |
||
1071 |
|||
1072 |
16 |
S = AIR_CAST(float, parm[0]); |
|
1073 |
8 |
B = AIR_CAST(float, parm[1]); |
|
1074 |
8 |
C = AIR_CAST(float, parm[2]); |
|
1075 |
✓✓ | 1920016 |
for (i=0; i<len; i++) { |
1076 |
960000 |
t = x[i]; |
|
1077 |
960000 |
t = AIR_ABS(t)/S; |
|
1078 |
✓✗✓✓ |
3840000 |
f[i] = _DDBCCUBIC(t, B, C)/(S*S*S); |
1079 |
} |
||
1080 |
8 |
} |
|
1081 |
|||
1082 |
static NrrdKernel |
||
1083 |
_nrrdKernelDDBC = { |
||
1084 |
"BCcubicDD", |
||
1085 |
3, _nrrdDDBCSup, returnZero, |
||
1086 |
_nrrdDDBC1_f, _nrrdDDBCN_f, _nrrdDDBC1_d, _nrrdDDBCN_d |
||
1087 |
}; |
||
1088 |
NrrdKernel *const |
||
1089 |
nrrdKernelBCCubicDD = &_nrrdKernelDDBC; |
||
1090 |
|||
1091 |
/* ------------------------------------------------------------ */ |
||
1092 |
|||
1093 |
/* if you've got the definition already, why not use it */ |
||
1094 |
#define _CTMR(x) _BCCUBIC(x, 0.0, 0.5) |
||
1095 |
|||
1096 |
static double |
||
1097 |
_nrrdCTMR1_d(double x, const double *parm) { |
||
1098 |
AIR_UNUSED(parm); |
||
1099 |
2160036 |
x = AIR_ABS(x); |
|
1100 |
✓✓✓✓ |
4217172 |
return _CTMR(x); |
1101 |
} |
||
1102 |
|||
1103 |
static float |
||
1104 |
_nrrdCTMR1_f(float x, const double *parm) { |
||
1105 |
AIR_UNUSED(parm); |
||
1106 |
720000 |
x = AIR_ABS(x); |
|
1107 |
✓✓✓✓ |
1405716 |
return AIR_CAST(float, _CTMR(x)); |
1108 |
} |
||
1109 |
|||
1110 |
static void |
||
1111 |
_nrrdCTMRN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1112 |
double t; |
||
1113 |
size_t i; |
||
1114 |
AIR_UNUSED(parm); |
||
1115 |
✓✓ | 4932036 |
for (i=0; i<len; i++) { |
1116 |
2325612 |
t = x[i]; |
|
1117 |
2325612 |
t = AIR_ABS(t); |
|
1118 |
✓✓✓✓ |
7583358 |
f[i] = _CTMR(t); |
1119 |
} |
||
1120 |
93604 |
} |
|
1121 |
|||
1122 |
static void |
||
1123 |
_nrrdCTMRN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1124 |
float t; |
||
1125 |
size_t i; |
||
1126 |
AIR_UNUSED(parm); |
||
1127 |
✓✓ | 720009 |
for (i=0; i<len; i++) { |
1128 |
360000 |
t = x[i]; |
|
1129 |
360000 |
t = AIR_ABS(t); |
|
1130 |
✓✓✓✓ |
1405716 |
f[i] = AIR_CAST(float, _CTMR(t)); |
1131 |
} |
||
1132 |
3 |
} |
|
1133 |
|||
1134 |
static NrrdKernel |
||
1135 |
_nrrdKernelCatmullRom = { |
||
1136 |
"catmull-rom", |
||
1137 |
0, returnTwo, returnOne, |
||
1138 |
_nrrdCTMR1_f, _nrrdCTMRN_f, _nrrdCTMR1_d, _nrrdCTMRN_d |
||
1139 |
}; |
||
1140 |
NrrdKernel *const |
||
1141 |
nrrdKernelCatmullRom = &_nrrdKernelCatmullRom; |
||
1142 |
|||
1143 |
|||
1144 |
static double |
||
1145 |
_nrrdCtmrSDSup(const double *parm) { |
||
1146 |
|||
1147 |
✓✓ | 501 |
return AIR_MAX(2.0, parm[0]); |
1148 |
} |
||
1149 |
|||
1150 |
static NrrdKernel |
||
1151 |
_nrrdKernelCatmullRomSupportDebug = { |
||
1152 |
"ctmrsup", |
||
1153 |
1, _nrrdCtmrSDSup, returnOne, |
||
1154 |
_nrrdCTMR1_f, _nrrdCTMRN_f, _nrrdCTMR1_d, _nrrdCTMRN_d |
||
1155 |
}; |
||
1156 |
NrrdKernel *const |
||
1157 |
nrrdKernelCatmullRomSupportDebug = &_nrrdKernelCatmullRomSupportDebug; |
||
1158 |
|||
1159 |
/* ------------------------------------------------------------ */ |
||
1160 |
|||
1161 |
/* if you've got the definition already, why not use it */ |
||
1162 |
#define _DCTMR(x) _DBCCUBIC(x, 0.0, 0.5) |
||
1163 |
|||
1164 |
static double |
||
1165 |
_nrrdDCTMR1_d(double x, const double *parm) { |
||
1166 |
int sgn; |
||
1167 |
AIR_UNUSED(parm); |
||
1168 |
✓✓ | 2700044 |
if (x < 0) { x = -x; sgn = -1; } else { sgn = 1; } |
1169 |
✓✓✓✓ |
4217172 |
return sgn*_DCTMR(x); |
1170 |
} |
||
1171 |
|||
1172 |
static float |
||
1173 |
_nrrdDCTMR1_f(float x, const double *parm) { |
||
1174 |
int sgn; |
||
1175 |
AIR_UNUSED(parm); |
||
1176 |
✓✓ | 900000 |
if (x < 0) { x = -x; sgn = -1; } else { sgn = 1; } |
1177 |
✓✓✓✓ |
1405716 |
return AIR_CAST(float, sgn*_DCTMR(x)); |
1178 |
} |
||
1179 |
|||
1180 |
static void |
||
1181 |
_nrrdDCTMRN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1182 |
int sgn; |
||
1183 |
double t; |
||
1184 |
size_t i; |
||
1185 |
AIR_UNUSED(parm); |
||
1186 |
✓✓ | 4194909 |
for (i=0; i<len; i++) { |
1187 |
1974600 |
t = x[i]; |
|
1188 |
✓✓ | 2961900 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1189 |
✓✓✓✓ |
6600516 |
f[i] = sgn*_DCTMR(t); |
1190 |
} |
||
1191 |
81903 |
} |
|
1192 |
|||
1193 |
static void |
||
1194 |
_nrrdDCTMRN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1195 |
int sgn; |
||
1196 |
float t; |
||
1197 |
size_t i; |
||
1198 |
AIR_UNUSED(parm); |
||
1199 |
✓✓ | 720009 |
for (i=0; i<len; i++) { |
1200 |
360000 |
t = x[i]; |
|
1201 |
✓✓ | 540000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1202 |
✓✓✓✓ |
1405716 |
f[i] = AIR_CAST(float, sgn*_DCTMR(t)); |
1203 |
} |
||
1204 |
3 |
} |
|
1205 |
|||
1206 |
static NrrdKernel |
||
1207 |
_nrrdKernelCatmullRomD = { |
||
1208 |
"catmull-romD", |
||
1209 |
0, returnTwo, returnZero, |
||
1210 |
_nrrdDCTMR1_f, _nrrdDCTMRN_f, _nrrdDCTMR1_d, _nrrdDCTMRN_d |
||
1211 |
}; |
||
1212 |
NrrdKernel *const |
||
1213 |
nrrdKernelCatmullRomD = &_nrrdKernelCatmullRomD; |
||
1214 |
|||
1215 |
static NrrdKernel |
||
1216 |
_nrrdKernelCatmullRomSupportDebugD = { |
||
1217 |
"ctmrsupD", |
||
1218 |
1, _nrrdCtmrSDSup, returnZero, |
||
1219 |
_nrrdDCTMR1_f, _nrrdDCTMRN_f, _nrrdDCTMR1_d, _nrrdDCTMRN_d |
||
1220 |
}; |
||
1221 |
NrrdKernel *const |
||
1222 |
nrrdKernelCatmullRomSupportDebugD = &_nrrdKernelCatmullRomSupportDebugD; |
||
1223 |
|||
1224 |
/* ------------------------------------------------------------ */ |
||
1225 |
|||
1226 |
/* if you've got the definition already, why not use it */ |
||
1227 |
#define _DDCTMR(x) _DDBCCUBIC(x, 0.0, 0.5) |
||
1228 |
|||
1229 |
static double |
||
1230 |
_nrrdDDCTMR1_d(double x, const double *parm) { |
||
1231 |
AIR_UNUSED(parm); |
||
1232 |
720036 |
x = AIR_ABS(x); |
|
1233 |
✓✓✓✓ |
1405752 |
return _DDCTMR(x); |
1234 |
} |
||
1235 |
|||
1236 |
static float |
||
1237 |
_nrrdDDCTMR1_f(float x, const double *parm) { |
||
1238 |
AIR_UNUSED(parm); |
||
1239 |
720000 |
x = AIR_ABS(x); |
|
1240 |
✓✓✓✓ |
1405716 |
return AIR_CAST(float, _DDCTMR(x)); |
1241 |
} |
||
1242 |
|||
1243 |
static void |
||
1244 |
_nrrdDDCTMRN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1245 |
double t; |
||
1246 |
size_t i; |
||
1247 |
AIR_UNUSED(parm); |
||
1248 |
✓✓ | 4194909 |
for (i=0; i<len; i++) { |
1249 |
1974600 |
t = x[i]; |
|
1250 |
1974600 |
t = AIR_ABS(t); |
|
1251 |
✓✓✓✓ |
6600516 |
f[i] = _DDCTMR(t); |
1252 |
} |
||
1253 |
81903 |
} |
|
1254 |
|||
1255 |
static void |
||
1256 |
_nrrdDDCTMRN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1257 |
float t; |
||
1258 |
size_t i; |
||
1259 |
AIR_UNUSED(parm); |
||
1260 |
✓✓ | 720009 |
for (i=0; i<len; i++) { |
1261 |
360000 |
t = x[i]; |
|
1262 |
360000 |
t = AIR_ABS(t); |
|
1263 |
✓✓✓✓ |
1405716 |
f[i] = AIR_CAST(float, _DDCTMR(t)); |
1264 |
} |
||
1265 |
3 |
} |
|
1266 |
|||
1267 |
static NrrdKernel |
||
1268 |
_nrrdKernelCatmullRomDD = { |
||
1269 |
"catmull-romDD", |
||
1270 |
0, returnTwo, returnZero, |
||
1271 |
_nrrdDDCTMR1_f, _nrrdDDCTMRN_f, _nrrdDDCTMR1_d, _nrrdDDCTMRN_d |
||
1272 |
}; |
||
1273 |
NrrdKernel *const |
||
1274 |
nrrdKernelCatmullRomDD = &_nrrdKernelCatmullRomDD; |
||
1275 |
|||
1276 |
static NrrdKernel |
||
1277 |
_nrrdKernelCatmullRomSupportDebugDD = { |
||
1278 |
"ctmrsupDD", |
||
1279 |
1, _nrrdCtmrSDSup, returnZero, |
||
1280 |
_nrrdDDCTMR1_f, _nrrdDDCTMRN_f, _nrrdDDCTMR1_d, _nrrdDDCTMRN_d |
||
1281 |
}; |
||
1282 |
NrrdKernel *const |
||
1283 |
nrrdKernelCatmullRomSupportDebugDD = &_nrrdKernelCatmullRomSupportDebugDD; |
||
1284 |
|||
1285 |
/* ------------------------------------------------------------ */ |
||
1286 |
|||
1287 |
#define _AQUARTIC(x, A) \ |
||
1288 |
(x >= 3.0 ? 0 : \ |
||
1289 |
(x >= 2.0 \ |
||
1290 |
? A*(-54 + x*(81 + x*(-45 + x*(11 - x)))) \ |
||
1291 |
: (x >= 1.0 \ |
||
1292 |
? 4 - 6*A + x*(-10 + 25*A + x*(9 - 33*A \ |
||
1293 |
+ x*(-3.5 + 17*A + x*(0.5 - 3*A)))) \ |
||
1294 |
: 1 + x*x*(-3 + 6*A + x*((2.5 - 10*A) + x*(-0.5 + 4*A)))))) |
||
1295 |
|||
1296 |
static double |
||
1297 |
_nrrdA4Sup(const double *parm) { |
||
1298 |
double S; |
||
1299 |
|||
1300 |
8 |
S = parm[0]; |
|
1301 |
4 |
return 3*S; |
|
1302 |
} |
||
1303 |
|||
1304 |
static double |
||
1305 |
_nrrdA41_d(double x, const double *parm) { |
||
1306 |
double S; |
||
1307 |
double A; |
||
1308 |
|||
1309 |
2880048 |
S = parm[0]; A = parm[1]; |
|
1310 |
1440024 |
x = AIR_ABS(x)/S; |
|
1311 |
✓✓✓✓ ✓✓ |
6720030 |
return _AQUARTIC(x, A)/S; |
1312 |
} |
||
1313 |
|||
1314 |
static float |
||
1315 |
_nrrdA41_f(float x, const double *parm) { |
||
1316 |
float A, S; |
||
1317 |
|||
1318 |
960000 |
S = AIR_CAST(float, parm[0]); A = AIR_CAST(float, parm[1]); |
|
1319 |
480000 |
x = AIR_ABS(x)/S; |
|
1320 |
✓✗✓✓ ✓✓ |
2240000 |
return AIR_CAST(float, _AQUARTIC(x, A)/S); |
1321 |
} |
||
1322 |
|||
1323 |
static void |
||
1324 |
_nrrdA4N_d(double *f, const double *x, size_t len, const double *parm) { |
||
1325 |
double S; |
||
1326 |
double t, A; |
||
1327 |
size_t i; |
||
1328 |
|||
1329 |
8 |
S = parm[0]; A = parm[1]; |
|
1330 |
✓✓ | 960008 |
for (i=0; i<len; i++) { |
1331 |
480000 |
t = x[i]; |
|
1332 |
480000 |
t = AIR_ABS(t)/S; |
|
1333 |
✓✗✓✓ ✓✓ |
2240000 |
f[i] = _AQUARTIC(t, A)/S; |
1334 |
} |
||
1335 |
4 |
} |
|
1336 |
|||
1337 |
static void |
||
1338 |
_nrrdA4N_f(float *f, const float *x, size_t len, const double *parm) { |
||
1339 |
float S, t, A; |
||
1340 |
size_t i; |
||
1341 |
|||
1342 |
8 |
S = AIR_CAST(float, parm[0]); A = AIR_CAST(float, parm[1]); |
|
1343 |
✓✓ | 960008 |
for (i=0; i<len; i++) { |
1344 |
480000 |
t = x[i]; |
|
1345 |
480000 |
t = AIR_ABS(t)/S; |
|
1346 |
✓✗✓✓ ✓✓ |
2240000 |
f[i] = AIR_CAST(float, _AQUARTIC(t, A)/S); |
1347 |
} |
||
1348 |
4 |
} |
|
1349 |
|||
1350 |
static NrrdKernel |
||
1351 |
_nrrdKernelA4 = { |
||
1352 |
"Aquartic", |
||
1353 |
2, _nrrdA4Sup, returnOne, |
||
1354 |
_nrrdA41_f, _nrrdA4N_f, _nrrdA41_d, _nrrdA4N_d |
||
1355 |
}; |
||
1356 |
NrrdKernel *const |
||
1357 |
nrrdKernelAQuartic = &_nrrdKernelA4; |
||
1358 |
|||
1359 |
/* ------------------------------------------------------------ */ |
||
1360 |
|||
1361 |
#define _DAQUARTIC(x, A) \ |
||
1362 |
(x >= 3.0 ? 0 : \ |
||
1363 |
(x >= 2.0 \ |
||
1364 |
? A*(81 + x*(-90 + x*(33 - 4*x))) \ |
||
1365 |
: (x >= 1.0 \ |
||
1366 |
? -10 + 25*A + x*(18 - 66*A + x*(-10.5 + 51*A + x*(2 - 12*A))) \ |
||
1367 |
: x*(-6 + 12*A + x*(7.5 - 30*A + x*(-2 + 16*A)))))) |
||
1368 |
|||
1369 |
static double |
||
1370 |
_nrrdDA4Sup(const double *parm) { |
||
1371 |
double S; |
||
1372 |
|||
1373 |
8 |
S = parm[0]; |
|
1374 |
4 |
return 3*S; |
|
1375 |
} |
||
1376 |
|||
1377 |
static double |
||
1378 |
_nrrdDA41_d(double x, const double *parm) { |
||
1379 |
double S; |
||
1380 |
double A; |
||
1381 |
int sgn = 1; |
||
1382 |
|||
1383 |
2880048 |
S = parm[0]; A = parm[1]; |
|
1384 |
✓✓ | 2160036 |
if (x < 0) { x = -x; sgn = -1; } |
1385 |
1440024 |
x /= S; |
|
1386 |
✓✓✓✓ ✓✓ |
6720030 |
return sgn*_DAQUARTIC(x, A)/(S*S); |
1387 |
} |
||
1388 |
|||
1389 |
static float |
||
1390 |
_nrrdDA41_f(float x, const double *parm) { |
||
1391 |
float A, S; |
||
1392 |
int sgn = 1; |
||
1393 |
|||
1394 |
960000 |
S = AIR_CAST(float, parm[0]); A = AIR_CAST(float, parm[1]); |
|
1395 |
✓✓ | 720000 |
if (x < 0) { x = -x; sgn = -1; } |
1396 |
480000 |
x /= S; |
|
1397 |
✓✗✓✓ ✓✓ |
2240000 |
return AIR_CAST(float, sgn*_DAQUARTIC(x, A)/(S*S)); |
1398 |
} |
||
1399 |
|||
1400 |
static void |
||
1401 |
_nrrdDA4N_d(double *f, const double *x, size_t len, const double *parm) { |
||
1402 |
double S; |
||
1403 |
double t, A; |
||
1404 |
size_t i; |
||
1405 |
int sgn; |
||
1406 |
|||
1407 |
8 |
S = parm[0]; A = parm[1]; |
|
1408 |
✓✓ | 960008 |
for (i=0; i<len; i++) { |
1409 |
480000 |
t = x[i]/S; |
|
1410 |
✓✓ | 720000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1411 |
✓✗✓✓ ✓✓ |
2240000 |
f[i] = sgn*_DAQUARTIC(t, A)/(S*S); |
1412 |
} |
||
1413 |
4 |
} |
|
1414 |
|||
1415 |
static void |
||
1416 |
_nrrdDA4N_f(float *f, const float *x, size_t len, const double *parm) { |
||
1417 |
float S, t, A; |
||
1418 |
size_t i; |
||
1419 |
int sgn; |
||
1420 |
|||
1421 |
8 |
S = AIR_CAST(float, parm[0]); A = AIR_CAST(float, parm[1]); |
|
1422 |
✓✓ | 960008 |
for (i=0; i<len; i++) { |
1423 |
480000 |
t = x[i]/S; |
|
1424 |
✓✓ | 720000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1425 |
✓✗✓✓ ✓✓ |
2240000 |
f[i] = AIR_CAST(float, sgn*_DAQUARTIC(t, A)/(S*S)); |
1426 |
} |
||
1427 |
4 |
} |
|
1428 |
|||
1429 |
static NrrdKernel |
||
1430 |
_nrrdKernelDA4 = { |
||
1431 |
"AquarticD", |
||
1432 |
2, _nrrdDA4Sup, returnZero, |
||
1433 |
_nrrdDA41_f, _nrrdDA4N_f, _nrrdDA41_d, _nrrdDA4N_d |
||
1434 |
}; |
||
1435 |
NrrdKernel *const |
||
1436 |
nrrdKernelAQuarticD = &_nrrdKernelDA4; |
||
1437 |
|||
1438 |
/* ------------------------------------------------------------ */ |
||
1439 |
|||
1440 |
#define _DDAQUARTIC(x, A) \ |
||
1441 |
(x >= 3.0 ? 0 : \ |
||
1442 |
(x >= 2.0 \ |
||
1443 |
? A*(-90 + x*(66 - x*12)) \ |
||
1444 |
: (x >= 1.0 \ |
||
1445 |
? 18 - 66*A + x*(-21 + 102*A + x*(6 - 36*A)) \ |
||
1446 |
: -6 + 12*A + x*(15 - 60*A + x*(-6 + 48*A))))) |
||
1447 |
|||
1448 |
static double |
||
1449 |
_nrrdDDA4Sup(const double *parm) { |
||
1450 |
double S; |
||
1451 |
|||
1452 |
8 |
S = parm[0]; |
|
1453 |
4 |
return 3*S; |
|
1454 |
} |
||
1455 |
|||
1456 |
static double |
||
1457 |
_nrrdDDA41_d(double x, const double *parm) { |
||
1458 |
double S; |
||
1459 |
double A; |
||
1460 |
|||
1461 |
960048 |
S = parm[0]; A = parm[1]; |
|
1462 |
480024 |
x = AIR_ABS(x)/S; |
|
1463 |
✓✓✓✓ ✓✓ |
2240048 |
return _DDAQUARTIC(x, A)/(S*S*S); |
1464 |
} |
||
1465 |
|||
1466 |
static float |
||
1467 |
_nrrdDDA41_f(float x, const double *parm) { |
||
1468 |
float S, A; |
||
1469 |
|||
1470 |
960000 |
S = AIR_CAST(float, parm[0]); A = AIR_CAST(float, parm[1]); |
|
1471 |
480000 |
x = AIR_ABS(x)/S; |
|
1472 |
✓✗✓✓ ✓✓ |
2240000 |
return _DDAQUARTIC(x, A)/(S*S*S); |
1473 |
} |
||
1474 |
|||
1475 |
static void |
||
1476 |
_nrrdDDA4N_d(double *f, const double *x, size_t len, const double *parm) { |
||
1477 |
double S; |
||
1478 |
double t, A; |
||
1479 |
size_t i; |
||
1480 |
|||
1481 |
8 |
S = parm[0]; A = parm[1]; |
|
1482 |
✓✓ | 960008 |
for (i=0; i<len; i++) { |
1483 |
480000 |
t = x[i]; |
|
1484 |
480000 |
t = AIR_ABS(t)/S; |
|
1485 |
✓✗✓✓ ✓✓ |
2240000 |
f[i] = _DDAQUARTIC(t, A)/(S*S*S); |
1486 |
} |
||
1487 |
4 |
} |
|
1488 |
|||
1489 |
static void |
||
1490 |
_nrrdDDA4N_f(float *f, const float *x, size_t len, const double *parm) { |
||
1491 |
float S, t, A; |
||
1492 |
size_t i; |
||
1493 |
|||
1494 |
8 |
S = AIR_CAST(float, parm[0]); A = AIR_CAST(float, parm[1]); |
|
1495 |
✓✓ | 960008 |
for (i=0; i<len; i++) { |
1496 |
480000 |
t = x[i]; |
|
1497 |
480000 |
t = AIR_ABS(t)/S; |
|
1498 |
✓✗✓✓ ✓✓ |
2240000 |
f[i] = _DDAQUARTIC(t, A)/(S*S*S); |
1499 |
} |
||
1500 |
4 |
} |
|
1501 |
|||
1502 |
static NrrdKernel |
||
1503 |
_nrrdKernelDDA4 = { |
||
1504 |
"AquarticDD", |
||
1505 |
2, _nrrdDDA4Sup, returnZero, |
||
1506 |
_nrrdDDA41_f, _nrrdDDA4N_f, _nrrdDDA41_d, _nrrdDDA4N_d |
||
1507 |
}; |
||
1508 |
NrrdKernel *const |
||
1509 |
nrrdKernelAQuarticDD = &_nrrdKernelDDA4; |
||
1510 |
|||
1511 |
/* ------------------------------------------------------------ */ |
||
1512 |
|||
1513 |
/* |
||
1514 |
** This is the unique, four-sample support, quintic, C^3 kernel, with 1st and |
||
1515 |
** 3rd derivatives zero at origin, which integrates to unity on [-2,2], which |
||
1516 |
** exactly reconstructs 0th and 1st order polynomials. Unfortunately it does |
||
1517 |
** NOT reconstruct 2nd order polynomials, so its not very useful. It worse |
||
1518 |
** than "one step down" from c4hexic (see below), since while its support and |
||
1519 |
** polynomial power is one less than c4hexic, it cannot reconstruct |
||
1520 |
** parabolas; c4hexic can reconstruct cubics. |
||
1521 |
** |
||
1522 |
** The same kernel is also available as nrrdKernelTMF w/ D,C,A = -1,3,2 == |
||
1523 |
** TMF_dn_c3_2ef == "tmf:n,3,2" == nrrdKernelTMF[0][4][2], the only advantage |
||
1524 |
** here being that you have access to the first and second derivatives of |
||
1525 |
** this quintic kernel as nrrdKernelC3QuinticD and nrrdKernelC3QuinticDD. |
||
1526 |
** |
||
1527 |
** By the way, TMF_d0_c3_3ef == TMF_dn_c3_3ef == "tmf:n,3,3", which can (by |
||
1528 |
** definition) reconstruct parabolas, has four-sample support, and has |
||
1529 |
** piecewise polynomial order *seven* |
||
1530 |
*/ |
||
1531 |
|||
1532 |
#define _C3QUINTIC(x) \ |
||
1533 |
(x >= 2.0 ? 0 : \ |
||
1534 |
(x >= 1.0 \ |
||
1535 |
? 0.8 + x*x*(-2 + x*(2 + x*(-0.75 + x*0.1))) \ |
||
1536 |
: 0.7 + x*x*(-1 + x*x*(0.75 - x*0.3)))) |
||
1537 |
|||
1538 |
static double |
||
1539 |
_c3quint1_d(double x, const double *parm) { |
||
1540 |
AIR_UNUSED(parm); |
||
1541 |
1440024 |
x = AIR_ABS(x); |
|
1542 |
✓✓✓✓ |
2880016 |
return _C3QUINTIC(x); |
1543 |
} |
||
1544 |
|||
1545 |
static float |
||
1546 |
_c3quint1_f(float x, const double *parm) { |
||
1547 |
AIR_UNUSED(parm); |
||
1548 |
480000 |
x = AIR_ABS(x); |
|
1549 |
✓✗✓✓ |
960000 |
return AIR_CAST(float, _C3QUINTIC(x)); |
1550 |
} |
||
1551 |
|||
1552 |
static void |
||
1553 |
_c3quintN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1554 |
double t; |
||
1555 |
size_t i; |
||
1556 |
AIR_UNUSED(parm); |
||
1557 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1558 |
240000 |
t = x[i]; |
|
1559 |
240000 |
t = AIR_ABS(t); |
|
1560 |
✓✗✓✓ |
960000 |
f[i] = _C3QUINTIC(t); |
1561 |
} |
||
1562 |
2 |
} |
|
1563 |
|||
1564 |
static void |
||
1565 |
_c3quintN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1566 |
float t; |
||
1567 |
size_t i; |
||
1568 |
AIR_UNUSED(parm); |
||
1569 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1570 |
240000 |
t = x[i]; |
|
1571 |
240000 |
t = AIR_ABS(t); |
|
1572 |
✓✗✓✓ |
960000 |
f[i] = AIR_CAST(float, _C3QUINTIC(t)); |
1573 |
} |
||
1574 |
2 |
} |
|
1575 |
|||
1576 |
static NrrdKernel |
||
1577 |
_c3quint = { |
||
1578 |
"C3Quintic", |
||
1579 |
0, returnTwo, returnOne, |
||
1580 |
_c3quint1_f, _c3quintN_f, _c3quint1_d, _c3quintN_d |
||
1581 |
}; |
||
1582 |
NrrdKernel *const |
||
1583 |
nrrdKernelC3Quintic = &_c3quint; |
||
1584 |
|||
1585 |
/* ------------------------------------------------------------ */ |
||
1586 |
|||
1587 |
#define _DC3QUINTIC(x) \ |
||
1588 |
(x >= 2.0 ? 0 : \ |
||
1589 |
(x >= 1.0 \ |
||
1590 |
? x*(-4 + x*(6 + x*(-3 + x*0.5))) \ |
||
1591 |
: x*(-2 + x*x*(3 - x*1.5)))) |
||
1592 |
|||
1593 |
static double |
||
1594 |
_Dc3quint1_d(double x, const double *parm) { |
||
1595 |
int sgn = 1; |
||
1596 |
AIR_UNUSED(parm); |
||
1597 |
✓✓ | 1800030 |
if (x < 0) { x = -x; sgn = -1; } |
1598 |
✓✓✓✓ |
3600012 |
return sgn*_DC3QUINTIC(x); |
1599 |
} |
||
1600 |
|||
1601 |
static float |
||
1602 |
_Dc3quint1_f(float x, const double *parm) { |
||
1603 |
int sgn = 1; |
||
1604 |
AIR_UNUSED(parm); |
||
1605 |
✓✓ | 600000 |
if (x < 0) { x = -x; sgn = -1; } |
1606 |
✓✗✓✓ |
1200000 |
return AIR_CAST(float, sgn*_DC3QUINTIC(x)); |
1607 |
} |
||
1608 |
|||
1609 |
static void |
||
1610 |
_Dc3quintN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1611 |
double t; |
||
1612 |
size_t i; |
||
1613 |
int sgn; |
||
1614 |
AIR_UNUSED(parm); |
||
1615 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1616 |
240000 |
t = x[i]; |
|
1617 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1618 |
✓✗✓✓ |
1200000 |
f[i] = sgn*_DC3QUINTIC(t); |
1619 |
} |
||
1620 |
2 |
} |
|
1621 |
|||
1622 |
static void |
||
1623 |
_Dc3quintN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1624 |
float t; |
||
1625 |
size_t i; |
||
1626 |
int sgn; |
||
1627 |
AIR_UNUSED(parm); |
||
1628 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1629 |
240000 |
t = x[i]; |
|
1630 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1631 |
✓✗✓✓ |
1200000 |
f[i] = AIR_CAST(float, sgn*_DC3QUINTIC(t)); |
1632 |
} |
||
1633 |
2 |
} |
|
1634 |
|||
1635 |
static NrrdKernel |
||
1636 |
_nrrdKernelDC3Quintic = { |
||
1637 |
"C3QuinticD", |
||
1638 |
0, returnTwo, returnZero, |
||
1639 |
_Dc3quint1_f, _Dc3quintN_f, _Dc3quint1_d, _Dc3quintN_d |
||
1640 |
}; |
||
1641 |
NrrdKernel *const |
||
1642 |
nrrdKernelC3QuinticD = &_nrrdKernelDC3Quintic; |
||
1643 |
|||
1644 |
/* ------------------------------------------------------------ */ |
||
1645 |
|||
1646 |
#define _DDC3QUINTIC(x) \ |
||
1647 |
(x >= 2.0 ? 0 : \ |
||
1648 |
(x >= 1.0 \ |
||
1649 |
? -4 + x*(12 + x*(-9 + x*2)) \ |
||
1650 |
: -2 + x*x*(9 - x*6))) |
||
1651 |
|||
1652 |
static double |
||
1653 |
_DDc3quint1_d(double x, const double *parm) { |
||
1654 |
AIR_UNUSED(parm); |
||
1655 |
480024 |
x = AIR_ABS(x); |
|
1656 |
✓✓✓✓ |
960024 |
return _DDC3QUINTIC(x); |
1657 |
} |
||
1658 |
|||
1659 |
static float |
||
1660 |
_DDc3quint1_f(float x, const double *parm) { |
||
1661 |
AIR_UNUSED(parm); |
||
1662 |
480000 |
x = AIR_ABS(x); |
|
1663 |
✓✗✓✓ |
960000 |
return AIR_CAST(float, _DDC3QUINTIC(x)); |
1664 |
} |
||
1665 |
|||
1666 |
static void |
||
1667 |
_DDc3quintN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1668 |
double t; |
||
1669 |
size_t i; |
||
1670 |
AIR_UNUSED(parm); |
||
1671 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1672 |
240000 |
t = x[i]; |
|
1673 |
240000 |
t = AIR_ABS(t); |
|
1674 |
✓✗✓✓ |
960000 |
f[i] = _DDC3QUINTIC(t); |
1675 |
} |
||
1676 |
2 |
} |
|
1677 |
|||
1678 |
static void |
||
1679 |
_DDc3quintN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1680 |
float t; |
||
1681 |
size_t i; |
||
1682 |
AIR_UNUSED(parm); |
||
1683 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1684 |
240000 |
t = x[i]; |
|
1685 |
240000 |
t = AIR_ABS(t); |
|
1686 |
✓✗✓✓ |
960000 |
f[i] = AIR_CAST(float, _DDC3QUINTIC(t)); |
1687 |
} |
||
1688 |
2 |
} |
|
1689 |
|||
1690 |
static NrrdKernel |
||
1691 |
_DDc3quint = { |
||
1692 |
"C3QuinticDD", |
||
1693 |
0, returnTwo, returnZero, |
||
1694 |
_DDc3quint1_f, _DDc3quintN_f, _DDc3quint1_d, _DDc3quintN_d |
||
1695 |
}; |
||
1696 |
NrrdKernel *const |
||
1697 |
nrrdKernelC3QuinticDD = &_DDc3quint; |
||
1698 |
|||
1699 |
/* ------------------------------------------------------------ */ |
||
1700 |
|||
1701 |
/* |
||
1702 |
** This is the unique, 6-sample support, hexic, C^4 kernel, with 1st and 3rd |
||
1703 |
** derivatives zero at origin, which integrates to unity on [-3,3], with 3rd |
||
1704 |
** order Taylor accuracy (errors start showing up when reconstructing 4th |
||
1705 |
** order polynomials) It doesn't interpolate, but its close, and it rings |
||
1706 |
** once. |
||
1707 |
** |
||
1708 |
** this is awfully close to, but not quite the same as, "tmf:n,3,4" == |
||
1709 |
** TMF_dn_c3_4ef == nrrdKernelTMF[0][4][4], which is only C^3 smooth |
||
1710 |
*/ |
||
1711 |
|||
1712 |
#define _C4HEXIC(x) \ |
||
1713 |
(x >= 3.0 \ |
||
1714 |
? 0 \ |
||
1715 |
: (x >= 2.0 \ |
||
1716 |
? 1539.0/160.0 + x*(-189.0/8.0 + x*(747.0/32.0 + x*(-12.0 + x*(109.0/32.0 + x*(-61.0/120.0 + x/32.0))))) \ |
||
1717 |
: (x >= 1.0 \ |
||
1718 |
? 3.0/160.0 + x*(35.0/8.0 + x*(-341.0/32.0 + x*(10.0 + x*(-147.0/32.0 + x*(25.0/24.0 - x*3.0/32.0))))) \ |
||
1719 |
: 69.0/80.0 + x*x*(-23.0/16.0 + x*x*(19.0/16.0 + x*(-7.0/12.0 + x/16.0))) ))) |
||
1720 |
|||
1721 |
static double |
||
1722 |
_c4hex1_d(double x, const double *parm) { |
||
1723 |
AIR_UNUSED(parm); |
||
1724 |
1440024 |
x = AIR_ABS(x); |
|
1725 |
✓✓✓✓ ✓✓ |
3360012 |
return _C4HEXIC(x); |
1726 |
} |
||
1727 |
|||
1728 |
static float |
||
1729 |
_c4hex1_f(float x, const double *parm) { |
||
1730 |
AIR_UNUSED(parm); |
||
1731 |
480000 |
x = AIR_ABS(x); |
|
1732 |
✓✗✓✓ ✓✓ |
1120000 |
return AIR_CAST(float, _C4HEXIC(x)); |
1733 |
} |
||
1734 |
|||
1735 |
static void |
||
1736 |
_c4hexN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1737 |
double t; |
||
1738 |
size_t i; |
||
1739 |
AIR_UNUSED(parm); |
||
1740 |
✓✓ | 525441 |
for (i=0; i<len; i++) { |
1741 |
260970 |
t = x[i]; |
|
1742 |
260970 |
t = AIR_ABS(t); |
|
1743 |
✓✗✓✓ ✓✓ |
1217860 |
f[i] = _C4HEXIC(t); |
1744 |
} |
||
1745 |
1167 |
} |
|
1746 |
|||
1747 |
static void |
||
1748 |
_c4hexN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1749 |
float t; |
||
1750 |
size_t i; |
||
1751 |
AIR_UNUSED(parm); |
||
1752 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1753 |
240000 |
t = x[i]; |
|
1754 |
240000 |
t = AIR_ABS(t); |
|
1755 |
✓✗✓✓ ✓✓ |
1120000 |
f[i] = AIR_CAST(float, _C4HEXIC(t)); |
1756 |
} |
||
1757 |
2 |
} |
|
1758 |
|||
1759 |
static NrrdKernel |
||
1760 |
_c4hex = { |
||
1761 |
"C4Hexic", |
||
1762 |
0, returnThree, returnOne, |
||
1763 |
_c4hex1_f, _c4hexN_f, _c4hex1_d, _c4hexN_d |
||
1764 |
}; |
||
1765 |
NrrdKernel *const |
||
1766 |
nrrdKernelC4Hexic = &_c4hex; |
||
1767 |
|||
1768 |
/* ------------------------------------------------------------ */ |
||
1769 |
|||
1770 |
#define _DC4HEXIC(x) \ |
||
1771 |
(x >= 3.0 \ |
||
1772 |
? 0 \ |
||
1773 |
: (x >= 2.0 \ |
||
1774 |
? -189.0/8.0 + x*(747.0/16.0 + x*(-36.0 + x*(109.0/8.0 + x*(-61.0/24.0 + x*(3.0/16.0))))) \ |
||
1775 |
: (x >= 1.0 \ |
||
1776 |
? 35.0/8.0 + x*(-341.0/16.0 + x*(30 + x*(-147.0/8.0 + x*(125.0/24.0 + x*(-9.0/16.0))))) \ |
||
1777 |
: x*(-23.0/8.0 + x*x*(19.0/4.0 + x*(-35.0/12.0 + x*(3.0/8.0)))) ))) |
||
1778 |
|||
1779 |
static double |
||
1780 |
_Dc4hex1_d(double x, const double *parm) { |
||
1781 |
int sgn = 1; |
||
1782 |
AIR_UNUSED(parm); |
||
1783 |
✓✓ | 1800030 |
if (x < 0) { x = -x; sgn = -1; } |
1784 |
✓✓✓✓ ✓✓ |
3360012 |
return sgn*_DC4HEXIC(x); |
1785 |
} |
||
1786 |
|||
1787 |
static float |
||
1788 |
_Dc4hex1_f(float x, const double *parm) { |
||
1789 |
int sgn = 1; |
||
1790 |
AIR_UNUSED(parm); |
||
1791 |
✓✓ | 600000 |
if (x < 0) { x = -x; sgn = -1; } |
1792 |
✓✗✓✓ ✓✓ |
1120000 |
return AIR_CAST(float, sgn*_DC4HEXIC(x)); |
1793 |
} |
||
1794 |
|||
1795 |
static void |
||
1796 |
_Dc4hexN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1797 |
double t; |
||
1798 |
size_t i; |
||
1799 |
int sgn; |
||
1800 |
AIR_UNUSED(parm); |
||
1801 |
✓✓ | 525441 |
for (i=0; i<len; i++) { |
1802 |
260970 |
t = x[i]; |
|
1803 |
✓✓ | 391455 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1804 |
✓✗✓✓ ✓✓ |
1217860 |
f[i] = sgn*_DC4HEXIC(t); |
1805 |
} |
||
1806 |
1167 |
} |
|
1807 |
|||
1808 |
static void |
||
1809 |
_Dc4hexN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1810 |
float t; |
||
1811 |
size_t i; |
||
1812 |
int sgn; |
||
1813 |
AIR_UNUSED(parm); |
||
1814 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1815 |
240000 |
t = x[i]; |
|
1816 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1817 |
✓✗✓✓ ✓✓ |
1120000 |
f[i] = AIR_CAST(float, sgn*_DC4HEXIC(t)); |
1818 |
} |
||
1819 |
2 |
} |
|
1820 |
|||
1821 |
static NrrdKernel |
||
1822 |
_nrrdKernelDC4hexic = { |
||
1823 |
"C4HexicD", |
||
1824 |
0, returnThree, returnZero, |
||
1825 |
_Dc4hex1_f, _Dc4hexN_f, _Dc4hex1_d, _Dc4hexN_d |
||
1826 |
}; |
||
1827 |
NrrdKernel *const |
||
1828 |
nrrdKernelC4HexicD = &_nrrdKernelDC4hexic; |
||
1829 |
|||
1830 |
/* ------------------------------------------------------------ */ |
||
1831 |
|||
1832 |
#define _DDC4HEXIC(x) \ |
||
1833 |
(x >= 3.0 \ |
||
1834 |
? 0 \ |
||
1835 |
: (x >= 2.0 \ |
||
1836 |
? 747.0/16.0 + x*(-72.0 + x*(327.0/8.0 + x*(-61.0/6.0 + x*15.0/16.0))) \ |
||
1837 |
: (x >= 1.0 \ |
||
1838 |
? -341.0/16.0 + x*(60 + x*(-441.0/8.0 + x*(125.0/6.0 - x*45.0/16.0))) \ |
||
1839 |
: -23.0/8.0 + x*x*(57.0/4.0 + x*(-35.0/3.0 + x*(15.0/8.0))) ))) |
||
1840 |
|||
1841 |
static double |
||
1842 |
_DDc4hex1_d(double x, const double *parm) { |
||
1843 |
AIR_UNUSED(parm); |
||
1844 |
1440024 |
x = AIR_ABS(x); |
|
1845 |
✓✓✓✓ ✓✓ |
3360012 |
return _DDC4HEXIC(x); |
1846 |
} |
||
1847 |
|||
1848 |
static float |
||
1849 |
_DDc4hex1_f(float x, const double *parm) { |
||
1850 |
AIR_UNUSED(parm); |
||
1851 |
480000 |
x = AIR_ABS(x); |
|
1852 |
✓✗✓✓ ✓✓ |
1120000 |
return AIR_CAST(float, _DDC4HEXIC(x)); |
1853 |
} |
||
1854 |
|||
1855 |
static void |
||
1856 |
_DDc4hexN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1857 |
double t; |
||
1858 |
size_t i; |
||
1859 |
AIR_UNUSED(parm); |
||
1860 |
✓✓ | 525441 |
for (i=0; i<len; i++) { |
1861 |
260970 |
t = x[i]; |
|
1862 |
260970 |
t = AIR_ABS(t); |
|
1863 |
✓✗✓✓ ✓✓ |
1217860 |
f[i] = _DDC4HEXIC(t); |
1864 |
} |
||
1865 |
1167 |
} |
|
1866 |
|||
1867 |
static void |
||
1868 |
_DDc4hexN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1869 |
float t; |
||
1870 |
size_t i; |
||
1871 |
AIR_UNUSED(parm); |
||
1872 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1873 |
240000 |
t = x[i]; |
|
1874 |
240000 |
t = AIR_ABS(t); |
|
1875 |
✓✗✓✓ ✓✓ |
1120000 |
f[i] = AIR_CAST(float, _DDC4HEXIC(t)); |
1876 |
} |
||
1877 |
2 |
} |
|
1878 |
|||
1879 |
static NrrdKernel |
||
1880 |
_DDc4hex = { |
||
1881 |
"C4HexicDD", |
||
1882 |
0, returnThree, returnZero, |
||
1883 |
_DDc4hex1_f, _DDc4hexN_f, _DDc4hex1_d, _DDc4hexN_d |
||
1884 |
}; |
||
1885 |
NrrdKernel *const |
||
1886 |
nrrdKernelC4HexicDD = &_DDc4hex; |
||
1887 |
|||
1888 |
/* ------------------------------------------------------------ */ |
||
1889 |
|||
1890 |
#define _DDDC4HEXIC(x) \ |
||
1891 |
(x >= 3.0 \ |
||
1892 |
? 0 \ |
||
1893 |
: (x >= 2.0 \ |
||
1894 |
? -72.0 + x*(327.0/4.0 + x*(-61.0/2.0 + 15*x/4)) \ |
||
1895 |
: (x >= 1.0 \ |
||
1896 |
? 60 + x*(-441.0/4.0 + x*(125.0/2.0 - 45*x/4)) \ |
||
1897 |
: x*(57.0/2.0 + x*(-35 + 15*x/2)) \ |
||
1898 |
))) |
||
1899 |
|||
1900 |
static double |
||
1901 |
_DDDc4hex1_d(double x, const double *parm) { |
||
1902 |
int sgn = 1; |
||
1903 |
AIR_UNUSED(parm); |
||
1904 |
✓✓ | 600030 |
if (x < 0) { x = -x; sgn = -1; } |
1905 |
✓✓✓✓ ✓✓ |
1120024 |
return sgn*_DDDC4HEXIC(x); |
1906 |
} |
||
1907 |
|||
1908 |
static float |
||
1909 |
_DDDc4hex1_f(float x, const double *parm) { |
||
1910 |
int sgn = 1; |
||
1911 |
AIR_UNUSED(parm); |
||
1912 |
✓✓ | 600000 |
if (x < 0) { x = -x; sgn = -1; } |
1913 |
✓✗✓✓ ✓✓ |
1120000 |
return AIR_CAST(float, sgn*_DDDC4HEXIC(x)); |
1914 |
} |
||
1915 |
|||
1916 |
static void |
||
1917 |
_DDDc4hexN_d(double *f, const double *x, size_t len, const double *parm) { |
||
1918 |
double t; |
||
1919 |
size_t i; |
||
1920 |
int sgn; |
||
1921 |
AIR_UNUSED(parm); |
||
1922 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1923 |
240000 |
t = x[i]; |
|
1924 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1925 |
✓✗✓✓ ✓✓ |
1120000 |
f[i] = sgn*_DDDC4HEXIC(t); |
1926 |
} |
||
1927 |
2 |
} |
|
1928 |
|||
1929 |
static void |
||
1930 |
_DDDc4hexN_f(float *f, const float *x, size_t len, const double *parm) { |
||
1931 |
float t; |
||
1932 |
size_t i; |
||
1933 |
int sgn; |
||
1934 |
AIR_UNUSED(parm); |
||
1935 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
1936 |
240000 |
t = x[i]; |
|
1937 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
1938 |
✓✗✓✓ ✓✓ |
1120000 |
f[i] = AIR_CAST(float, sgn*_DDDC4HEXIC(t)); |
1939 |
} |
||
1940 |
2 |
} |
|
1941 |
|||
1942 |
static NrrdKernel |
||
1943 |
_nrrdKernelDDDC4hexic = { |
||
1944 |
"C4HexicDDD", |
||
1945 |
0, returnThree, returnZero, |
||
1946 |
_DDDc4hex1_f, _DDDc4hexN_f, _DDDc4hex1_d, _DDDc4hexN_d |
||
1947 |
}; |
||
1948 |
NrrdKernel *const |
||
1949 |
nrrdKernelC4HexicDDD = &_nrrdKernelDDDC4hexic; |
||
1950 |
|||
1951 |
|||
1952 |
/* ------------- approximate inverse of c4h ------------------------- */ |
||
1953 |
/* see comments around "_bspl3_ANI" in bsplKernel.c */ |
||
1954 |
|||
1955 |
static double |
||
1956 |
_c4hex_ANI_kvals[12] = { |
||
1957 |
1.1906949847244948336, |
||
1958 |
-0.13537708971729194940, |
||
1959 |
0.047024535491780434571, |
||
1960 |
-0.0088462060502312555095, |
||
1961 |
0.0022443498051487024049, |
||
1962 |
-0.00048639680369511914410, |
||
1963 |
0.00011421848629250278186, |
||
1964 |
-0.000025727759438407893986, |
||
1965 |
5.9204264168395963454e-6, |
||
1966 |
-1.3468552403175349134e-6, |
||
1967 |
3.0637649910394681441e-7, |
||
1968 |
-5.5762487950611026674e-8}; |
||
1969 |
|||
1970 |
static double |
||
1971 |
_c4hex_ANI_sup(const double *parm) { |
||
1972 |
AIR_UNUSED(parm); |
||
1973 |
2 |
return 12.5; |
|
1974 |
} |
||
1975 |
|||
1976 |
#define C4HEX_ANI(ret, tmp, x) \ |
||
1977 |
tmp = AIR_CAST(unsigned int, x+0.5); \ |
||
1978 |
if (tmp < 12) { \ |
||
1979 |
ret = _c4hex_ANI_kvals[tmp]; \ |
||
1980 |
} else { \ |
||
1981 |
ret = 0.0; \ |
||
1982 |
} |
||
1983 |
|||
1984 |
static double |
||
1985 |
_c4hex_ANI_1d(double x, const double *parm) { |
||
1986 |
double ax, r; unsigned int tmp; |
||
1987 |
AIR_UNUSED(parm); |
||
1988 |
240012 |
ax = AIR_ABS(x); |
|
1989 |
✓✓ | 230406 |
C4HEX_ANI(r, tmp, ax); |
1990 |
120006 |
return r; |
|
1991 |
} |
||
1992 |
|||
1993 |
static float |
||
1994 |
_c4hex_ANI_1f(float x, const double *parm) { |
||
1995 |
double ax, r; unsigned int tmp; |
||
1996 |
AIR_UNUSED(parm); |
||
1997 |
240000 |
ax = AIR_ABS(x); |
|
1998 |
✓✓ | 230400 |
C4HEX_ANI(r, tmp, ax); |
1999 |
120000 |
return AIR_CAST(float, r); |
|
2000 |
} |
||
2001 |
|||
2002 |
static void |
||
2003 |
_c4hex_ANI_Nd(double *f, const double *x, size_t len, const double *parm) { |
||
2004 |
double ax, r; unsigned int tmp; |
||
2005 |
size_t i; |
||
2006 |
AIR_UNUSED(parm); |
||
2007 |
✓✓ | 240003 |
for (i=0; i<len; i++) { |
2008 |
120000 |
ax = x[i]; ax = AIR_ABS(ax); |
|
2009 |
✓✓ | 230400 |
C4HEX_ANI(r, tmp, ax); |
2010 |
120000 |
f[i] = r; |
|
2011 |
} |
||
2012 |
1 |
} |
|
2013 |
|||
2014 |
static void |
||
2015 |
_c4hex_ANI_Nf(float *f, const float *x, size_t len, const double *parm) { |
||
2016 |
double ax, r; unsigned int tmp; |
||
2017 |
size_t i; |
||
2018 |
AIR_UNUSED(parm); |
||
2019 |
✓✓ | 240003 |
for (i=0; i<len; i++) { |
2020 |
120000 |
ax = x[i]; ax = AIR_ABS(ax); |
|
2021 |
✓✓ | 230400 |
C4HEX_ANI(r, tmp, ax); |
2022 |
120000 |
f[i] = AIR_CAST(float, r); |
|
2023 |
} |
||
2024 |
1 |
} |
|
2025 |
|||
2026 |
static NrrdKernel |
||
2027 |
_nrrdKernelC4HexicApproxInverse = { |
||
2028 |
"C4HexicAI", 0, |
||
2029 |
_c4hex_ANI_sup, returnOne, |
||
2030 |
_c4hex_ANI_1f, _c4hex_ANI_Nf, |
||
2031 |
_c4hex_ANI_1d, _c4hex_ANI_Nd |
||
2032 |
}; |
||
2033 |
NrrdKernel *const |
||
2034 |
nrrdKernelC4HexicApproxInverse = &_nrrdKernelC4HexicApproxInverse; |
||
2035 |
|||
2036 |
/* ------------------------- c5septic ------------------------------ */ |
||
2037 |
|||
2038 |
/* |
||
2039 |
** This is the unique, 8-sample support, C^5 kernel, piecewise order-7 |
||
2040 |
** with 4th order Taylor accuracy (errors start showing up when |
||
2041 |
** reconstructing 5th order polynomials). Coincidentally, it has zero |
||
2042 |
** 1st and 3rd deriv at the origin, and it integrates to unity on |
||
2043 |
** [-4,4]. It doesn't interpolate, but its close; it rings twice. */ |
||
2044 |
|||
2045 |
#define _C5SEPT0(x) (0.9379776601998824 + x*x*(-1.654320987654321 + x*x*(1.073045267489712 + x*x*(-0.44997427983539096 + x*0.13978909465020575)))) |
||
2046 |
#define _C5SEPT1(x) (0.04651675485008818 + x*(-0.7377829218106996 + x*(0.9699074074074074 + x*(0.18531378600823045 + x*(-0.7839506172839507 + x*(0.2357253086419753 + x*(0.12021604938271604 - x*0.054552469135802466))))))) |
||
2047 |
#define _C5SEPT2(x) (-0.01860670194003527 + x*(0.14022633744855967 + x*(-0.16296296296296298 + x*(-0.09825102880658436 + x*(0.28858024691358025 + x*(-0.18858024691358025 + x*(0.04405864197530864 - x*0.0013631687242798354))))))) |
||
2048 |
#define _C5SEPT3(x) (0.003101116990005879 + x*(-0.014223251028806585 + x*(0.02021604938271605 + x*(0.003729423868312757 + x*(-0.0411522633744856 + x*(0.04714506172839506 + x*(-0.023199588477366254 + x*0.004383450911228689))))))) |
||
2049 |
#define _C5SEPT(i, x) \ |
||
2050 |
(0 == i ? _C5SEPT0(x) \ |
||
2051 |
: (1 == i ? _C5SEPT1(x) \ |
||
2052 |
: (2 == i ? _C5SEPT2(x) \ |
||
2053 |
: (3 == i ? _C5SEPT3(x) \ |
||
2054 |
: 0.0)))) |
||
2055 |
|||
2056 |
static double |
||
2057 |
_c5sept1_d(double x, const double *parm) { |
||
2058 |
unsigned int xi; |
||
2059 |
AIR_UNUSED(parm); |
||
2060 |
1440024 |
x = AIR_ABS(x); |
|
2061 |
720012 |
xi = AIR_CAST(unsigned int, x); |
|
2062 |
720012 |
x -= xi; |
|
2063 |
✓✓✓✓ ✓✓✓✓ |
3240060 |
return _C5SEPT(xi, x); |
2064 |
} |
||
2065 |
|||
2066 |
static float |
||
2067 |
_c5sept1_f(float x, const double *parm) { |
||
2068 |
unsigned int xi; |
||
2069 |
AIR_UNUSED(parm); |
||
2070 |
480000 |
x = AIR_ABS(x); |
|
2071 |
240000 |
xi = AIR_CAST(unsigned int, x); |
|
2072 |
240000 |
x -= AIR_CAST(float, xi); |
|
2073 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
return AIR_CAST(float, _C5SEPT(xi, x)); |
2074 |
} |
||
2075 |
|||
2076 |
static void |
||
2077 |
_c5septN_d(double *f, const double *x, size_t len, const double *parm) { |
||
2078 |
unsigned int ti; |
||
2079 |
double t; |
||
2080 |
size_t i; |
||
2081 |
AIR_UNUSED(parm); |
||
2082 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
2083 |
240000 |
t = x[i]; |
|
2084 |
240000 |
t = AIR_ABS(t); |
|
2085 |
240000 |
ti = AIR_CAST(unsigned int, t); |
|
2086 |
240000 |
t -= ti; |
|
2087 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
f[i] = _C5SEPT(ti, t); |
2088 |
} |
||
2089 |
2 |
} |
|
2090 |
|||
2091 |
static void |
||
2092 |
_c5septN_f(float *f, const float *x, size_t len, const double *parm) { |
||
2093 |
unsigned int ti; |
||
2094 |
float t; |
||
2095 |
size_t i; |
||
2096 |
AIR_UNUSED(parm); |
||
2097 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
2098 |
240000 |
t = x[i]; |
|
2099 |
240000 |
t = AIR_ABS(t); |
|
2100 |
240000 |
ti = AIR_CAST(unsigned int, t); |
|
2101 |
240000 |
t -= AIR_CAST(float, ti); |
|
2102 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
f[i] = AIR_CAST(float, _C5SEPT(ti, t)); |
2103 |
} |
||
2104 |
2 |
} |
|
2105 |
|||
2106 |
static NrrdKernel |
||
2107 |
_c5sept = { |
||
2108 |
"C5Septic", |
||
2109 |
0, returnFour, returnOne, |
||
2110 |
_c5sept1_f, _c5septN_f, _c5sept1_d, _c5septN_d |
||
2111 |
}; |
||
2112 |
NrrdKernel *const |
||
2113 |
nrrdKernelC5Septic = &_c5sept; |
||
2114 |
|||
2115 |
#define _DC5SEPT0(x) (x*(-3.308641975308642 + x*x*(4.292181069958848 + x*x*(-2.6998456790123457 + x*0.9785236625514403)))) |
||
2116 |
#define _DC5SEPT1(x) (-0.7377829218106996 + x*(1.9398148148148149 + x*(0.5559413580246914 + x*(-3.1358024691358026 + x*(1.1786265432098766 + x*(0.7212962962962963 - x*0.3818672839506173)))))) |
||
2117 |
#define _DC5SEPT2(x) (0.14022633744855967 + x*(-0.32592592592592595 + x*(-0.29475308641975306 + x*(1.154320987654321 + x*(-0.9429012345679012 + x*(0.26435185185185184 - x*0.009542181069958848)))))) |
||
2118 |
#define _DC5SEPT3(x) (-0.014223251028806585 + x*(0.0404320987654321 + x*(0.011188271604938271 + x*(-0.1646090534979424 + x*(0.2357253086419753 + x*(-0.13919753086419753 + x*0.03068415637860082)))))) |
||
2119 |
#define _DC5SEPT(i, x) \ |
||
2120 |
(0 == i ? _DC5SEPT0(x) \ |
||
2121 |
: (1 == i ? _DC5SEPT1(x) \ |
||
2122 |
: (2 == i ? _DC5SEPT2(x) \ |
||
2123 |
: (3 == i ? _DC5SEPT3(x) \ |
||
2124 |
: 0.0)))) |
||
2125 |
|||
2126 |
static double |
||
2127 |
_dc5sept1_d(double x, const double *parm) { |
||
2128 |
unsigned int xi; |
||
2129 |
int sgn = 1; |
||
2130 |
AIR_UNUSED(parm); |
||
2131 |
✓✓ | 1800030 |
if (x < 0) { x = -x; sgn = -1; } |
2132 |
720012 |
xi = AIR_CAST(unsigned int, x); |
|
2133 |
720012 |
x -= xi; |
|
2134 |
✓✓✓✓ ✓✓✓✓ |
3240060 |
return sgn*_DC5SEPT(xi, x); |
2135 |
} |
||
2136 |
|||
2137 |
static float |
||
2138 |
_dc5sept1_f(float x, const double *parm) { |
||
2139 |
unsigned int xi; |
||
2140 |
int sgn = 1; |
||
2141 |
AIR_UNUSED(parm); |
||
2142 |
✓✓ | 600000 |
if (x < 0) { x = -x; sgn = -1; } |
2143 |
240000 |
xi = AIR_CAST(unsigned int, x); |
|
2144 |
240000 |
x -= AIR_CAST(float, xi); |
|
2145 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
return AIR_CAST(float, sgn*_DC5SEPT(xi, x)); |
2146 |
} |
||
2147 |
|||
2148 |
static void |
||
2149 |
_dc5septN_d(double *f, const double *x, size_t len, const double *parm) { |
||
2150 |
unsigned int ti; |
||
2151 |
double t; |
||
2152 |
size_t i; |
||
2153 |
int sgn; |
||
2154 |
AIR_UNUSED(parm); |
||
2155 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
2156 |
240000 |
t = x[i]; |
|
2157 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
2158 |
240000 |
ti = AIR_CAST(unsigned int, t); |
|
2159 |
240000 |
t -= ti; |
|
2160 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
f[i] = sgn*_DC5SEPT(ti, t); |
2161 |
} |
||
2162 |
2 |
} |
|
2163 |
|||
2164 |
static void |
||
2165 |
_dc5septN_f(float *f, const float *x, size_t len, const double *parm) { |
||
2166 |
unsigned int ti; |
||
2167 |
float t; |
||
2168 |
size_t i; |
||
2169 |
int sgn = 1; |
||
2170 |
AIR_UNUSED(parm); |
||
2171 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
2172 |
240000 |
t = x[i]; |
|
2173 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
2174 |
240000 |
ti = AIR_CAST(unsigned int, t); |
|
2175 |
240000 |
t -= AIR_CAST(float, ti); |
|
2176 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
f[i] = AIR_CAST(float, sgn*_DC5SEPT(ti, t)); |
2177 |
} |
||
2178 |
2 |
} |
|
2179 |
|||
2180 |
static NrrdKernel |
||
2181 |
_dc5sept = { |
||
2182 |
"C5SepticD", |
||
2183 |
0, returnFour, returnZero, |
||
2184 |
_dc5sept1_f, _dc5septN_f, _dc5sept1_d, _dc5septN_d |
||
2185 |
}; |
||
2186 |
NrrdKernel *const |
||
2187 |
nrrdKernelC5SepticD = &_dc5sept; |
||
2188 |
|||
2189 |
#define _DDC5SEPT0(x) (-3.308641975308642 + x*x*(12.876543209876543 + x*x*(-13.499228395061728 + x*5.871141975308642))) |
||
2190 |
#define _DDC5SEPT1(x) (1.9398148148148149 + x*(1.1118827160493827 + x*(-9.407407407407407 + x*(4.714506172839506 + x*(3.6064814814814814 - x*2.2912037037037036))))) |
||
2191 |
#define _DDC5SEPT2(x) (-0.32592592592592595 + x*(-0.5895061728395061 + x*(3.462962962962963 + x*(-3.771604938271605 + x*(1.3217592592592593 - x*0.05725308641975309))))) |
||
2192 |
#define _DDC5SEPT3(x) (0.0404320987654321 + x*(0.022376543209876542 + x*(-0.49382716049382713 + x*(0.9429012345679012 + x*(-0.6959876543209876 + x*0.18410493827160493))))) |
||
2193 |
#define _DDC5SEPT(i, x) \ |
||
2194 |
(0 == i ? _DDC5SEPT0(x) \ |
||
2195 |
: (1 == i ? _DDC5SEPT1(x) \ |
||
2196 |
: (2 == i ? _DDC5SEPT2(x) \ |
||
2197 |
: (3 == i ? _DDC5SEPT3(x) \ |
||
2198 |
: 0.0)))) |
||
2199 |
|||
2200 |
static double |
||
2201 |
_ddc5sept1_d(double x, const double *parm) { |
||
2202 |
unsigned int xi; |
||
2203 |
AIR_UNUSED(parm); |
||
2204 |
1440024 |
x = AIR_ABS(x); |
|
2205 |
720012 |
xi = AIR_CAST(unsigned int, x); |
|
2206 |
720012 |
x -= xi; |
|
2207 |
✓✓✓✓ ✓✓✓✓ |
3240060 |
return _DDC5SEPT(xi, x); |
2208 |
} |
||
2209 |
|||
2210 |
static float |
||
2211 |
_ddc5sept1_f(float x, const double *parm) { |
||
2212 |
unsigned int xi; |
||
2213 |
AIR_UNUSED(parm); |
||
2214 |
480000 |
x = AIR_ABS(x); |
|
2215 |
240000 |
xi = AIR_CAST(unsigned int, x); |
|
2216 |
240000 |
x -= AIR_CAST(float, xi); |
|
2217 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
return AIR_CAST(float, _DDC5SEPT(xi, x)); |
2218 |
} |
||
2219 |
|||
2220 |
static void |
||
2221 |
_ddc5septN_d(double *f, const double *x, size_t len, const double *parm) { |
||
2222 |
unsigned int ti; |
||
2223 |
double t; |
||
2224 |
size_t i; |
||
2225 |
AIR_UNUSED(parm); |
||
2226 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
2227 |
240000 |
t = x[i]; |
|
2228 |
240000 |
t = AIR_ABS(t); |
|
2229 |
240000 |
ti = AIR_CAST(unsigned int, t); |
|
2230 |
240000 |
t -= ti; |
|
2231 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
f[i] = _DDC5SEPT(ti, t); |
2232 |
} |
||
2233 |
2 |
} |
|
2234 |
|||
2235 |
static void |
||
2236 |
_ddc5septN_f(float *f, const float *x, size_t len, const double *parm) { |
||
2237 |
unsigned int ti; |
||
2238 |
float t; |
||
2239 |
size_t i; |
||
2240 |
AIR_UNUSED(parm); |
||
2241 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
2242 |
240000 |
t = x[i]; |
|
2243 |
240000 |
t = AIR_ABS(t); |
|
2244 |
240000 |
ti = AIR_CAST(unsigned int, t); |
|
2245 |
240000 |
t -= AIR_CAST(float, ti); |
|
2246 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
f[i] = AIR_CAST(float, _DDC5SEPT(ti, t)); |
2247 |
} |
||
2248 |
2 |
} |
|
2249 |
|||
2250 |
static NrrdKernel |
||
2251 |
_ddc5sept = { |
||
2252 |
"C5SepticDD", |
||
2253 |
0, returnFour, returnZero, |
||
2254 |
_ddc5sept1_f, _ddc5septN_f, _ddc5sept1_d, _ddc5septN_d |
||
2255 |
}; |
||
2256 |
NrrdKernel *const |
||
2257 |
nrrdKernelC5SepticDD = &_ddc5sept; |
||
2258 |
|||
2259 |
#define _DDDC5SEPT0(x) (x*(25.75308641975309 + x*x*(-53.99691358024691 + x*29.35570987654321))) |
||
2260 |
#define _DDDC5SEPT1(x) (1.111882716049383 + x*(-18.81481481481481 + x*(14.14351851851852 + x*(14.42592592592593 - x*11.45601851851852)))) |
||
2261 |
#define _DDDC5SEPT2(x) (-0.5895061728395062 + x*(6.925925925925926 + x*(-11.31481481481481 + x*(5.287037037037037 - x*0.2862654320987654)))) |
||
2262 |
#define _DDDC5SEPT3(x) (0.02237654320987654 + x*(-0.9876543209876543 + x*(2.828703703703704 + x*(-2.783950617283951 + x*0.9205246913580247)))) |
||
2263 |
#define _DDDC5SEPT(i, x) \ |
||
2264 |
(0 == i ? _DDDC5SEPT0(x) \ |
||
2265 |
: (1 == i ? _DDDC5SEPT1(x) \ |
||
2266 |
: (2 == i ? _DDDC5SEPT2(x) \ |
||
2267 |
: (3 == i ? _DDDC5SEPT3(x) \ |
||
2268 |
: 0.0)))) |
||
2269 |
|||
2270 |
static double |
||
2271 |
_dddc5sept1_d(double x, const double *parm) { |
||
2272 |
unsigned int xi; |
||
2273 |
int sgn = 1; |
||
2274 |
AIR_UNUSED(parm); |
||
2275 |
✓✓ | 600030 |
if (x < 0) { x = -x; sgn = -1; } |
2276 |
240012 |
xi = AIR_CAST(unsigned int, x); |
|
2277 |
240012 |
x -= xi; |
|
2278 |
✓✓✓✓ ✓✓✓✓ |
1080060 |
return sgn*_DDDC5SEPT(xi, x); |
2279 |
} |
||
2280 |
|||
2281 |
static float |
||
2282 |
_dddc5sept1_f(float x, const double *parm) { |
||
2283 |
unsigned int xi; |
||
2284 |
int sgn = 1; |
||
2285 |
AIR_UNUSED(parm); |
||
2286 |
✓✓ | 600000 |
if (x < 0) { x = -x; sgn = -1; } |
2287 |
240000 |
xi = AIR_CAST(unsigned int, x); |
|
2288 |
240000 |
x -= AIR_CAST(float, xi); |
|
2289 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
return AIR_CAST(float, sgn*_DDDC5SEPT(xi, x)); |
2290 |
} |
||
2291 |
|||
2292 |
static void |
||
2293 |
_dddc5septN_d(double *f, const double *x, size_t len, const double *parm) { |
||
2294 |
unsigned int ti; |
||
2295 |
double t; |
||
2296 |
size_t i; |
||
2297 |
int sgn; |
||
2298 |
AIR_UNUSED(parm); |
||
2299 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
2300 |
240000 |
t = x[i]; |
|
2301 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
2302 |
240000 |
ti = AIR_CAST(unsigned int, t); |
|
2303 |
240000 |
t -= ti; |
|
2304 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
f[i] = sgn*_DDDC5SEPT(ti, t); |
2305 |
} |
||
2306 |
2 |
} |
|
2307 |
|||
2308 |
static void |
||
2309 |
_dddc5septN_f(float *f, const float *x, size_t len, const double *parm) { |
||
2310 |
unsigned int ti; |
||
2311 |
float t; |
||
2312 |
size_t i; |
||
2313 |
int sgn = 1; |
||
2314 |
AIR_UNUSED(parm); |
||
2315 |
✓✓ | 480006 |
for (i=0; i<len; i++) { |
2316 |
240000 |
t = x[i]; |
|
2317 |
✓✓ | 360000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
2318 |
240000 |
ti = AIR_CAST(unsigned int, t); |
|
2319 |
240000 |
t -= AIR_CAST(float, ti); |
|
2320 |
✓✓✓✓ ✓✓✓✗ |
1080000 |
f[i] = AIR_CAST(float, sgn*_DDDC5SEPT(ti, t)); |
2321 |
} |
||
2322 |
2 |
} |
|
2323 |
|||
2324 |
static NrrdKernel |
||
2325 |
_dddc5sept = { |
||
2326 |
"C5SepticDDD", |
||
2327 |
0, returnFour, returnZero, |
||
2328 |
_dddc5sept1_f, _dddc5septN_f, _dddc5sept1_d, _dddc5septN_d |
||
2329 |
}; |
||
2330 |
NrrdKernel *const |
||
2331 |
nrrdKernelC5SepticDDD = &_dddc5sept; |
||
2332 |
|||
2333 |
/* note that this implies a much more accurate inverse than is given |
||
2334 |
for the splines or other kernels; this is a consequence of GLK |
||
2335 |
re-purposing the Mathematica expressions for the bpsln7 inverse, |
||
2336 |
which is unfortunate: c5septic is nearly interpolating, so far |
||
2337 |
fewer terms would suffice */ |
||
2338 |
#define C5SEPT_AI_LEN 26 |
||
2339 |
static double |
||
2340 |
_c5sept_ANI_kvals[C5SEPT_AI_LEN] = { |
||
2341 |
1.072662863909143543451743, |
||
2342 |
-0.05572032001443187610952953, |
||
2343 |
0.02453993146603215267432700, |
||
2344 |
-0.005922375635530229254855750, |
||
2345 |
0.0009781882769025851448681918, |
||
2346 |
-0.0002499281491108793120774480, |
||
2347 |
0.00005196973116762945530292666, |
||
2348 |
-0.00001090007030248955413371701, |
||
2349 |
2.425581976693179040189747e-6, |
||
2350 |
-5.143328756144314306529358e-7, |
||
2351 |
1.109572595055083858393193e-7, |
||
2352 |
-2.400323559797703961855318e-8, |
||
2353 |
5.151959978856239469272136e-9, |
||
2354 |
-1.111431289951609447815300e-9, |
||
2355 |
2.394624249806782312051293e-10, |
||
2356 |
-5.155654818408366273965675e-11, |
||
2357 |
1.111091879440261302739584e-11, |
||
2358 |
-2.393303168472914213194646e-12, |
||
2359 |
5.155527554392687415035171e-13, |
||
2360 |
-1.110707782883835600110634e-13, |
||
2361 |
2.392644268109899456937863e-14, |
||
2362 |
-5.154377464414088544322752e-15, |
||
2363 |
1.110376957658466603291262e-15, |
||
2364 |
-2.391459139266885907929865e-16, |
||
2365 |
5.137528165538909945741180e-17, |
||
2366 |
-9.024576392408067896802608e-18}; |
||
2367 |
|||
2368 |
static double |
||
2369 |
_c5sept_ANI_sup(const double *parm) { |
||
2370 |
AIR_UNUSED(parm); |
||
2371 |
2 |
return C5SEPT_AI_LEN + 0.5; |
|
2372 |
} |
||
2373 |
|||
2374 |
static double |
||
2375 |
_c5sept_ANI_int(const double *parm) { |
||
2376 |
AIR_UNUSED(parm); |
||
2377 |
2 |
return 1.0; |
|
2378 |
} |
||
2379 |
|||
2380 |
#define C5SEPT_ANI(ret, tmp, x) \ |
||
2381 |
tmp = AIR_CAST(unsigned int, x+0.5); \ |
||
2382 |
if (tmp < C5SEPT_AI_LEN) { \ |
||
2383 |
ret = _c5sept_ANI_kvals[tmp]; \ |
||
2384 |
} else { \ |
||
2385 |
ret = 0.0; \ |
||
2386 |
} |
||
2387 |
|||
2388 |
static double |
||
2389 |
_c5sept_ANI_1d(double x, const double *parm) { |
||
2390 |
double ax, r; unsigned int tmp; |
||
2391 |
AIR_UNUSED(parm); |
||
2392 |
|||
2393 |
240012 |
ax = AIR_ABS(x); |
|
2394 |
✓✓ | 235478 |
C5SEPT_ANI(r, tmp, ax); |
2395 |
120006 |
return r; |
|
2396 |
} |
||
2397 |
|||
2398 |
static float |
||
2399 |
_c5sept_ANI_1f(float x, const double *parm) { |
||
2400 |
double ax, r; unsigned int tmp; |
||
2401 |
AIR_UNUSED(parm); |
||
2402 |
|||
2403 |
240000 |
ax = AIR_ABS(x); |
|
2404 |
✓✓ | 235472 |
C5SEPT_ANI(r, tmp, ax); |
2405 |
120000 |
return AIR_CAST(float, r); |
|
2406 |
} |
||
2407 |
|||
2408 |
static void |
||
2409 |
_c5sept_ANI_Nd(double *f, const double *x, size_t len, const double *parm) { |
||
2410 |
double ax, r; unsigned int tmp; |
||
2411 |
size_t i; |
||
2412 |
AIR_UNUSED(parm); |
||
2413 |
|||
2414 |
✓✓ | 240003 |
for (i=0; i<len; i++) { |
2415 |
120000 |
ax = x[i]; ax = AIR_ABS(ax); |
|
2416 |
✓✓ | 235472 |
C5SEPT_ANI(r, tmp, ax); |
2417 |
120000 |
f[i] = r; |
|
2418 |
} |
||
2419 |
1 |
} |
|
2420 |
|||
2421 |
static void |
||
2422 |
_c5sept_ANI_Nf(float *f, const float *x, size_t len, const double *parm) { |
||
2423 |
double ax, r; unsigned int tmp; |
||
2424 |
size_t i; |
||
2425 |
AIR_UNUSED(parm); |
||
2426 |
|||
2427 |
✓✓ | 240003 |
for (i=0; i<len; i++) { |
2428 |
120000 |
ax = x[i]; ax = AIR_ABS(ax); |
|
2429 |
✓✓ | 235472 |
C5SEPT_ANI(r, tmp, ax); |
2430 |
120000 |
f[i] = AIR_CAST(float, r); |
|
2431 |
} |
||
2432 |
1 |
} |
|
2433 |
|||
2434 |
static NrrdKernel |
||
2435 |
_nrrdKernelC5SepticApproxInverse = { |
||
2436 |
"C5SepticAI", 0, |
||
2437 |
_c5sept_ANI_sup, _c5sept_ANI_int, |
||
2438 |
_c5sept_ANI_1f, _c5sept_ANI_Nf, |
||
2439 |
_c5sept_ANI_1d, _c5sept_ANI_Nd |
||
2440 |
}; |
||
2441 |
NrrdKernel *const |
||
2442 |
nrrdKernelC5SepticApproxInverse = &_nrrdKernelC5SepticApproxInverse; |
||
2443 |
|||
2444 |
/* ------------------------------------------------------------ */ |
||
2445 |
|||
2446 |
#define _GAUSS(x, sig, cut) ( \ |
||
2447 |
x >= sig*cut ? 0 \ |
||
2448 |
: exp(-x*x/(2.0*sig*sig))/(sig*2.50662827463100050241)) |
||
2449 |
|||
2450 |
static double |
||
2451 |
_nrrdGInt(const double *parm) { |
||
2452 |
double cut; |
||
2453 |
|||
2454 |
3470 |
cut = parm[1]; |
|
2455 |
1735 |
return airErf(cut/sqrt(2.0)); |
|
2456 |
} |
||
2457 |
|||
2458 |
static double |
||
2459 |
_nrrdGSup(const double *parm) { |
||
2460 |
double sig, cut; |
||
2461 |
|||
2462 |
16 |
sig = parm[0]; |
|
2463 |
8 |
cut = parm[1]; |
|
2464 |
8 |
return sig*cut; |
|
2465 |
} |
||
2466 |
|||
2467 |
static double |
||
2468 |
_nrrdG1_d(double x, const double *parm) { |
||
2469 |
double sig, cut; |
||
2470 |
|||
2471 |
4320072 |
sig = parm[0]; |
|
2472 |
2160036 |
cut = parm[1]; |
|
2473 |
2160036 |
x = AIR_ABS(x); |
|
2474 |
✓✓ | 6480062 |
return _GAUSS(x, sig, cut); |
2475 |
} |
||
2476 |
|||
2477 |
static float |
||
2478 |
_nrrdG1_f(float x, const double *parm) { |
||
2479 |
float sig, cut; |
||
2480 |
|||
2481 |
1440000 |
sig = AIR_CAST(float, parm[0]); |
|
2482 |
720000 |
cut = AIR_CAST(float, parm[1]); |
|
2483 |
720000 |
x = AIR_ABS(x); |
|
2484 |
✓✗ | 2160000 |
return AIR_CAST(float, _GAUSS(x, sig, cut)); |
2485 |
} |
||
2486 |
|||
2487 |
static void |
||
2488 |
_nrrdGN_d(double *f, const double *x, size_t len, const double *parm) { |
||
2489 |
double sig, cut, t; |
||
2490 |
size_t i; |
||
2491 |
|||
2492 |
3468 |
sig = parm[0]; |
|
2493 |
1734 |
cut = parm[1]; |
|
2494 |
✓✓ | 1567884 |
for (i=0; i<len; i++) { |
2495 |
782208 |
t = x[i]; |
|
2496 |
782208 |
t = AIR_ABS(t); |
|
2497 |
✓✓ | 2345760 |
f[i] = _GAUSS(t, sig, cut); |
2498 |
} |
||
2499 |
1734 |
} |
|
2500 |
|||
2501 |
static void |
||
2502 |
_nrrdGN_f(float *f, const float *x, size_t len, const double *parm) { |
||
2503 |
float sig, cut, t; |
||
2504 |
size_t i; |
||
2505 |
|||
2506 |
12 |
sig = AIR_CAST(float, parm[0]); |
|
2507 |
6 |
cut = AIR_CAST(float, parm[1]); |
|
2508 |
✓✓ | 1440012 |
for (i=0; i<len; i++) { |
2509 |
720000 |
t = x[i]; |
|
2510 |
720000 |
t = AIR_ABS(t); |
|
2511 |
✓✗ | 2160000 |
f[i] = AIR_CAST(float, _GAUSS(t, sig, cut)); |
2512 |
} |
||
2513 |
6 |
} |
|
2514 |
|||
2515 |
static NrrdKernel |
||
2516 |
_nrrdKernelG = { |
||
2517 |
"gauss", |
||
2518 |
2, _nrrdGSup, _nrrdGInt, |
||
2519 |
_nrrdG1_f, _nrrdGN_f, _nrrdG1_d, _nrrdGN_d |
||
2520 |
}; |
||
2521 |
NrrdKernel *const |
||
2522 |
nrrdKernelGaussian = &_nrrdKernelG; |
||
2523 |
|||
2524 |
/* ------------------------------------------------------------ */ |
||
2525 |
|||
2526 |
#define _DISCRETEGAUSS(xx, sig, abscut) \ |
||
2527 |
(sig > 0 \ |
||
2528 |
? (xx > abscut \ |
||
2529 |
? 0 \ |
||
2530 |
: airBesselInExpScaled(AIR_CAST(int, xx + 0.5), sig*sig)) \ |
||
2531 |
: xx <= 0.5) |
||
2532 |
|||
2533 |
/* the last line used to be AIR_MAX(0.5, (ret)), but the problem was |
||
2534 |
that even for reasonable cutoffs, like sigma=6, there would be a |
||
2535 |
sudden change in the non-zero values at the edge of the kernel with |
||
2536 |
slowly increasing sigma. The real solution is to have a smarter way |
||
2537 |
of determining where to cut-off this particular kernel, the |
||
2538 |
discrete gaussian, when the values are at the low level one would |
||
2539 |
expect with "sigma=6" when talking about a continuous Gaussian */ |
||
2540 |
#define _DGABSCUT(ret, sig, cut) \ |
||
2541 |
(ret) = 0.5 + ceil((sig)*(cut)); \ |
||
2542 |
(ret) = AIR_MAX(2.5, (ret)) |
||
2543 |
|||
2544 |
static double |
||
2545 |
_nrrdDiscGaussianSup(const double *parm) { |
||
2546 |
double ret; |
||
2547 |
|||
2548 |
12 |
_DGABSCUT(ret, parm[0], parm[1]); |
|
2549 |
6 |
return ret; |
|
2550 |
} |
||
2551 |
|||
2552 |
/* the functions are out of their usual definition order because we |
||
2553 |
use the function evaluation to determine the integral, rather than |
||
2554 |
trying to do it analytically */ |
||
2555 |
|||
2556 |
static double |
||
2557 |
_nrrdDiscGaussian1_d(double xx, const double *parm) { |
||
2558 |
double sig, cut; |
||
2559 |
|||
2560 |
1440204 |
sig = parm[0]; |
|
2561 |
720102 |
_DGABSCUT(cut, sig, parm[1]); |
|
2562 |
720102 |
xx = AIR_ABS(xx); |
|
2563 |
✓✗✓✓ |
2880372 |
return _DISCRETEGAUSS(xx, sig, cut); |
2564 |
} |
||
2565 |
|||
2566 |
static double |
||
2567 |
_nrrdDiscGaussianInt(const double *parm) { |
||
2568 |
double sum, cut; |
||
2569 |
int ii, supp; |
||
2570 |
|||
2571 |
12 |
_DGABSCUT(cut, parm[0], parm[1]); |
|
2572 |
6 |
supp = AIR_CAST(int, cut); |
|
2573 |
sum = 0.0; |
||
2574 |
✓✓ | 144 |
for (ii=-supp; ii<=supp; ii++) { |
2575 |
66 |
sum += _nrrdDiscGaussian1_d(ii, parm); |
|
2576 |
} |
||
2577 |
6 |
return sum; |
|
2578 |
} |
||
2579 |
|||
2580 |
static float |
||
2581 |
_nrrdDiscGaussian1_f(float xx, const double *parm) { |
||
2582 |
double sig, cut; |
||
2583 |
|||
2584 |
1440000 |
sig = parm[0]; |
|
2585 |
720000 |
_DGABSCUT(cut, sig, parm[1]); |
|
2586 |
720000 |
xx = AIR_ABS(xx); |
|
2587 |
✓✗✓✗ |
2880000 |
return AIR_CAST(float, _DISCRETEGAUSS(xx, sig, cut)); |
2588 |
} |
||
2589 |
|||
2590 |
static void |
||
2591 |
_nrrdDiscGaussianN_d(double *f, const double *x, |
||
2592 |
size_t len, const double *parm) { |
||
2593 |
double sig, cut, tt; |
||
2594 |
size_t ii; |
||
2595 |
|||
2596 |
12 |
sig = parm[0]; |
|
2597 |
6 |
_DGABSCUT(cut, sig, parm[1]); |
|
2598 |
✓✓ | 1440012 |
for (ii=0; ii<len; ii++) { |
2599 |
720000 |
tt = AIR_ABS(x[ii]); |
|
2600 |
✓✗✓✗ |
2880000 |
f[ii] = _DISCRETEGAUSS(tt, sig, cut); |
2601 |
} |
||
2602 |
6 |
} |
|
2603 |
|||
2604 |
static void |
||
2605 |
_nrrdDiscGaussianN_f(float *f, const float *x, size_t len, const double *parm) { |
||
2606 |
double sig, cut, tt; |
||
2607 |
size_t ii; |
||
2608 |
|||
2609 |
12 |
sig = parm[0]; |
|
2610 |
6 |
_DGABSCUT(cut, sig, parm[1]); |
|
2611 |
✓✓ | 1440012 |
for (ii=0; ii<len; ii++) { |
2612 |
720000 |
tt = AIR_ABS(x[ii]); |
|
2613 |
✓✗✓✗ |
2880000 |
f[ii] = AIR_CAST(float, _DISCRETEGAUSS(tt, sig, cut)); |
2614 |
} |
||
2615 |
6 |
} |
|
2616 |
|||
2617 |
static NrrdKernel |
||
2618 |
_nrrdKernelDiscreteGaussian = { |
||
2619 |
"discretegauss", 2, |
||
2620 |
_nrrdDiscGaussianSup, _nrrdDiscGaussianInt, |
||
2621 |
_nrrdDiscGaussian1_f, _nrrdDiscGaussianN_f, |
||
2622 |
_nrrdDiscGaussian1_d, _nrrdDiscGaussianN_d |
||
2623 |
}; |
||
2624 |
NrrdKernel *const |
||
2625 |
nrrdKernelDiscreteGaussian = &_nrrdKernelDiscreteGaussian; |
||
2626 |
|||
2627 |
/* The current implementation of nrrdKernelDiscreteGaussian, with the current |
||
2628 |
implementation of airBesselInExpScaled, has problems for large |
||
2629 |
sigma. Until those are fixed, this is a suggested limit on how big sigma |
||
2630 |
(kparm[0]) can be and still have an accurate blurring kernel. This |
||
2631 |
problem can be avoided completely by doing the blurring in frequency |
||
2632 |
space, which is implemented in teem/src/gage/stackBlur.c's |
||
2633 |
_stackBlurDiscreteGaussFFT(), although that has its own problem: in places |
||
2634 |
where a signal really should zero, the FFT can produce some very |
||
2635 |
low-amplitude noise (and hence new extrema) */ |
||
2636 |
const double nrrdKernelDiscreteGaussianGoodSigmaMax = 6.0; |
||
2637 |
|||
2638 |
/* ------------------------------------------------------------ */ |
||
2639 |
|||
2640 |
#define _DGAUSS(x, sig, cut) ( \ |
||
2641 |
x >= sig*cut ? 0 \ |
||
2642 |
: -exp(-x*x/(2.0*sig*sig))*x/(sig*sig*sig*2.50662827463100050241)) |
||
2643 |
|||
2644 |
static double |
||
2645 |
_nrrdDGInt(const double *parm) { |
||
2646 |
AIR_UNUSED(parm); |
||
2647 |
14 |
return 0; |
|
2648 |
} |
||
2649 |
|||
2650 |
static double |
||
2651 |
_nrrdDGSup(const double *parm) { |
||
2652 |
double sig, cut; |
||
2653 |
|||
2654 |
16 |
sig = parm[0]; |
|
2655 |
8 |
cut = parm[1]; |
|
2656 |
8 |
return sig*cut; |
|
2657 |
} |
||
2658 |
|||
2659 |
static double |
||
2660 |
_nrrdDG1_d(double x, const double *parm) { |
||
2661 |
double sig, cut; |
||
2662 |
int sgn = 1; |
||
2663 |
|||
2664 |
4320072 |
sig = parm[0]; |
|
2665 |
2160036 |
cut = parm[1]; |
|
2666 |
✓✓ | 3240054 |
if (x < 0) { x = -x; sgn = -1; } |
2667 |
✓✓ | 6480062 |
return sgn*_DGAUSS(x, sig, cut); |
2668 |
} |
||
2669 |
|||
2670 |
static float |
||
2671 |
_nrrdDG1_f(float x, const double *parm) { |
||
2672 |
float sig, cut; |
||
2673 |
int sgn = 1; |
||
2674 |
|||
2675 |
1440000 |
sig = AIR_CAST(float, parm[0]); |
|
2676 |
720000 |
cut = AIR_CAST(float, parm[1]); |
|
2677 |
✓✓ | 1080000 |
if (x < 0) { x = -x; sgn = -1; } |
2678 |
✓✗ | 2160000 |
return AIR_CAST(float, sgn*_DGAUSS(x, sig, cut)); |
2679 |
} |
||
2680 |
|||
2681 |
static void |
||
2682 |
_nrrdDGN_d(double *f, const double *x, size_t len, const double *parm) { |
||
2683 |
double sig, cut, t; |
||
2684 |
size_t i; |
||
2685 |
int sgn; |
||
2686 |
|||
2687 |
3468 |
sig = parm[0]; |
|
2688 |
1734 |
cut = parm[1]; |
|
2689 |
✓✓ | 1567884 |
for (i=0; i<len; i++) { |
2690 |
782208 |
t = x[i]; |
|
2691 |
✓✓ | 1173312 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
2692 |
✓✓ | 2345760 |
f[i] = sgn*_DGAUSS(t, sig, cut); |
2693 |
} |
||
2694 |
1734 |
} |
|
2695 |
|||
2696 |
static void |
||
2697 |
_nrrdDGN_f(float *f, const float *x, size_t len, const double *parm) { |
||
2698 |
float sig, cut, t; |
||
2699 |
size_t i; |
||
2700 |
int sgn; |
||
2701 |
|||
2702 |
12 |
sig = AIR_CAST(float, parm[0]); |
|
2703 |
6 |
cut = AIR_CAST(float, parm[1]); |
|
2704 |
✓✓ | 1440012 |
for (i=0; i<len; i++) { |
2705 |
720000 |
t = x[i]; |
|
2706 |
✓✓ | 1080000 |
if (t < 0) { t = -t; sgn = -1; } else { sgn = 1; } |
2707 |
✓✗ | 2160000 |
f[i] = AIR_CAST(float, sgn*_DGAUSS(t, sig, cut)); |
2708 |
} |
||
2709 |
6 |
} |
|
2710 |
|||
2711 |
static NrrdKernel |
||
2712 |
_nrrdKernelDG = { |
||
2713 |
"gaussD", |
||
2714 |
2, _nrrdDGSup, _nrrdDGInt, |
||
2715 |
_nrrdDG1_f, _nrrdDGN_f, _nrrdDG1_d, _nrrdDGN_d |
||
2716 |
}; |
||
2717 |
NrrdKernel *const |
||
2718 |
nrrdKernelGaussianD = &_nrrdKernelDG; |
||
2719 |
|||
2720 |
/* ------------------------------------------------------------ */ |
||
2721 |
|||
2722 |
#define _DDGAUSS(x, sig, cut) ( \ |
||
2723 |
x >= sig*cut ? 0 \ |
||
2724 |
: exp(-x*x/(2.0*sig*sig))*(x*x-sig*sig) / \ |
||
2725 |
(sig*sig*sig*sig*sig*2.50662827463100050241)) |
||
2726 |
|||
2727 |
static double |
||
2728 |
_nrrdDDGInt(const double *parm) { |
||
2729 |
double sig, cut; |
||
2730 |
|||
2731 |
14 |
sig = parm[0]; |
|
2732 |
7 |
cut = parm[1]; |
|
2733 |
7 |
return -0.79788456080286535587*cut*exp(-cut*cut/2)/(sig*sig); |
|
2734 |
} |
||
2735 |
|||
2736 |
static double |
||
2737 |
_nrrdDDGSup(const double *parm) { |
||
2738 |
double sig, cut; |
||
2739 |
|||
2740 |
16 |
sig = parm[0]; |
|
2741 |
8 |
cut = parm[1]; |
|
2742 |
8 |
return sig*cut; |
|
2743 |
} |
||
2744 |
|||
2745 |
static double |
||
2746 |
_nrrdDDG1_d(double x, const double *parm) { |
||
2747 |
double sig, cut; |
||
2748 |
|||
2749 |
1440072 |
sig = parm[0]; |
|
2750 |
720036 |
cut = parm[1]; |
|
2751 |
720036 |
x = AIR_ABS(x); |
|
2752 |
✓✓ | 2160072 |
return _DDGAUSS(x, sig, cut); |
2753 |
} |
||
2754 |
|||
2755 |
static float |
||
2756 |
_nrrdDDG1_f(float x, const double *parm) { |
||
2757 |
float sig, cut; |
||
2758 |
|||
2759 |
1440000 |
sig = AIR_CAST(float, parm[0]); |
|
2760 |
720000 |
cut = AIR_CAST(float, parm[1]); |
|
2761 |
720000 |
x = AIR_ABS(x); |
|
2762 |
✓✗ | 2160000 |
return AIR_CAST(float, _DDGAUSS(x, sig, cut)); |
2763 |
} |
||
2764 |
|||
2765 |
static void |
||
2766 |
_nrrdDDGN_d(double *f, const double *x, size_t len, const double *parm) { |
||
2767 |
double sig, cut, t; |
||
2768 |
size_t i; |
||
2769 |
|||
2770 |
3468 |
sig = parm[0]; |
|
2771 |
1734 |
cut = parm[1]; |
|
2772 |
✓✓ | 1567884 |
for (i=0; i<len; i++) { |
2773 |
782208 |
t = x[i]; |
|
2774 |
782208 |
t = AIR_ABS(t); |
|
2775 |
✓✓ | 2345760 |
f[i] = _DDGAUSS(t, sig, cut); |
2776 |
} |
||
2777 |
1734 |
} |
|
2778 |
|||
2779 |
static void |
||
2780 |
_nrrdDDGN_f(float *f, const float *x, size_t len, const double *parm) { |
||
2781 |
float sig, cut, t; |
||
2782 |
size_t i; |
||
2783 |
|||
2784 |
12 |
sig = AIR_CAST(float, parm[0]); |
|
2785 |
6 |
cut = AIR_CAST(float, parm[1]); |
|
2786 |
✓✓ | 1440012 |
for (i=0; i<len; i++) { |
2787 |
720000 |
t = x[i]; |
|
2788 |
720000 |
t = AIR_ABS(t); |
|
2789 |
✓✗ | 2160000 |
f[i] = AIR_CAST(float, _DDGAUSS(t, sig, cut)); |
2790 |
} |
||
2791 |
6 |
} |
|
2792 |
|||
2793 |
static NrrdKernel |
||
2794 |
_nrrdKernelDDG = { |
||
2795 |
"gaussDD", |
||
2796 |
2, _nrrdDDGSup, _nrrdDDGInt, |
||
2797 |
_nrrdDDG1_f, _nrrdDDGN_f, _nrrdDDG1_d, _nrrdDDGN_d |
||
2798 |
}; |
||
2799 |
NrrdKernel *const |
||
2800 |
nrrdKernelGaussianDD = &_nrrdKernelDDG; |
||
2801 |
|||
2802 |
|||
2803 |
/* ------------------------------------------------------------ */ |
||
2804 |
|||
2805 |
NrrdKernel * |
||
2806 |
_nrrdKernelStrToKern(char *str) { |
||
2807 |
|||
2808 |
✓✓ | 744 |
if (!strcmp("zero", str)) return nrrdKernelZero; |
2809 |
✓✓ | 370 |
if (!strcmp("box", str)) return nrrdKernelBox; |
2810 |
✓✓ | 366 |
if (!strcmp("boxsup", str)) return nrrdKernelBoxSupportDebug; |
2811 |
✓✓ | 362 |
if (!strcmp("cos4sup", str)) return nrrdKernelCos4SupportDebug; |
2812 |
✓✓ | 358 |
if (!strcmp("cos4supd", str)) return nrrdKernelCos4SupportDebugD; |
2813 |
✓✓ | 354 |
if (!strcmp("cos4supdd", str)) return nrrdKernelCos4SupportDebugDD; |
2814 |
✓✓ | 350 |
if (!strcmp("cos4supddd", str)) return nrrdKernelCos4SupportDebugDDD; |
2815 |
✓✓ | 346 |
if (!strcmp("cheap", str)) return nrrdKernelCheap; |
2816 |
✗✓ | 338 |
if (!strcmp("hermiteflag", str)) return nrrdKernelHermiteScaleSpaceFlag; |
2817 |
✗✓ | 338 |
if (!strcmp("hermite", str)) return nrrdKernelHermiteScaleSpaceFlag; |
2818 |
✓✓ | 340 |
if (!strcmp("hermitess", str)) return nrrdKernelHermiteScaleSpaceFlag; |
2819 |
✗✓ | 336 |
if (!strcmp("herm", str)) return nrrdKernelHermiteScaleSpaceFlag; |
2820 |
✓✓ | 340 |
if (!strcmp("tent", str)) return nrrdKernelTent; |
2821 |
✗✓ | 332 |
if (!strcmp("tentd", str)) return nrrdKernelForwDiff; |
2822 |
✗✓ | 332 |
if (!strcmp("forwdiff", str)) return nrrdKernelForwDiff; |
2823 |
✓✓ | 336 |
if (!strcmp("fordif", str)) return nrrdKernelForwDiff; |
2824 |
✗✓ | 328 |
if (!strcmp("centdiff", str)) return nrrdKernelCentDiff; |
2825 |
✓✓ | 332 |
if (!strcmp("cendif", str)) return nrrdKernelCentDiff; |
2826 |
✓✓ | 340 |
if (!strcmp("bccubic", str)) return nrrdKernelBCCubic; |
2827 |
✗✓ | 308 |
if (!strcmp("cubic", str)) return nrrdKernelBCCubic; |
2828 |
✓✓ | 324 |
if (!strcmp("bccubicd", str)) return nrrdKernelBCCubicD; |
2829 |
✗✓ | 292 |
if (!strcmp("cubicd", str)) return nrrdKernelBCCubicD; |
2830 |
✓✓ | 308 |
if (!strcmp("bccubicdd", str)) return nrrdKernelBCCubicDD; |
2831 |
✗✓ | 276 |
if (!strcmp("cubicdd", str)) return nrrdKernelBCCubicDD; |
2832 |
✗✓ | 276 |
if (!strcmp("ctmr", str)) return nrrdKernelCatmullRom; |
2833 |
✓✓ | 278 |
if (!strcmp("catmull-rom", str)) return nrrdKernelCatmullRom; |
2834 |
✗✓ | 274 |
if (!strcmp("ctmrd", str)) return nrrdKernelCatmullRomD; |
2835 |
✓✓ | 276 |
if (!strcmp("catmull-romd", str)) return nrrdKernelCatmullRomD; |
2836 |
✗✓ | 272 |
if (!strcmp("ctmrdd", str)) return nrrdKernelCatmullRomDD; |
2837 |
✓✓ | 274 |
if (!strcmp("catmull-romdd", str)) return nrrdKernelCatmullRomDD; |
2838 |
✓✓ | 274 |
if (!strcmp("ctmrsup", str)) return nrrdKernelCatmullRomSupportDebug; |
2839 |
✓✓ | 270 |
if (!strcmp("ctmrsupd", str)) return nrrdKernelCatmullRomSupportDebugD; |
2840 |
✓✓ | 266 |
if (!strcmp("ctmrsupdd", str)) return nrrdKernelCatmullRomSupportDebugDD; |
2841 |
✓✓ | 266 |
if (!strcmp("aquartic", str)) return nrrdKernelAQuartic; |
2842 |
✗✓ | 250 |
if (!strcmp("quartic", str)) return nrrdKernelAQuartic; |
2843 |
✓✓ | 258 |
if (!strcmp("aquarticd", str)) return nrrdKernelAQuarticD; |
2844 |
✗✓ | 242 |
if (!strcmp("quarticd", str)) return nrrdKernelAQuarticD; |
2845 |
✓✓ | 250 |
if (!strcmp("aquarticdd", str)) return nrrdKernelAQuarticDD; |
2846 |
✗✓ | 234 |
if (!strcmp("quarticdd", str)) return nrrdKernelAQuarticDD; |
2847 |
✓✓ | 238 |
if (!strcmp("c3quintic", str)) return nrrdKernelC3Quintic; |
2848 |
✗✓ | 230 |
if (!strcmp("c3q", str)) return nrrdKernelC3Quintic; |
2849 |
✓✓ | 234 |
if (!strcmp("c3quinticd", str)) return nrrdKernelC3QuinticD; |
2850 |
✗✓ | 226 |
if (!strcmp("c3qd", str)) return nrrdKernelC3QuinticD; |
2851 |
✓✓ | 230 |
if (!strcmp("c3quinticdd", str)) return nrrdKernelC3QuinticDD; |
2852 |
✗✓ | 222 |
if (!strcmp("c3qdd", str)) return nrrdKernelC3QuinticDD; |
2853 |
✓✓ | 226 |
if (!strcmp("c4hexic", str)) return nrrdKernelC4Hexic; |
2854 |
✗✓ | 218 |
if (!strcmp("c4hai", str)) return nrrdKernelC4HexicApproxInverse; |
2855 |
✓✓ | 220 |
if (!strcmp("c4hexicai", str)) return nrrdKernelC4HexicApproxInverse; |
2856 |
✗✓ | 216 |
if (!strcmp("c4h", str)) return nrrdKernelC4Hexic; |
2857 |
✓✓ | 220 |
if (!strcmp("c4hexicd", str)) return nrrdKernelC4HexicD; |
2858 |
✗✓ | 212 |
if (!strcmp("c4hd", str)) return nrrdKernelC4HexicD; |
2859 |
✓✓ | 216 |
if (!strcmp("c4hexicdd", str)) return nrrdKernelC4HexicDD; |
2860 |
✗✓ | 208 |
if (!strcmp("c4hdd", str)) return nrrdKernelC4HexicDD; |
2861 |
✓✓ | 212 |
if (!strcmp("c4hexicddd", str)) return nrrdKernelC4HexicDDD; |
2862 |
✗✓ | 204 |
if (!strcmp("c4hddd", str)) return nrrdKernelC4HexicDDD; |
2863 |
✓✓ | 208 |
if (!strcmp("c5septic", str)) return nrrdKernelC5Septic; |
2864 |
✓✓ | 204 |
if (!strcmp("c5septicd", str)) return nrrdKernelC5SepticD; |
2865 |
✓✓ | 200 |
if (!strcmp("c5septicdd", str)) return nrrdKernelC5SepticDD; |
2866 |
✓✓ | 196 |
if (!strcmp("c5septicddd", str))return nrrdKernelC5SepticDDD; |
2867 |
✓✓ | 190 |
if (!strcmp("c5septicai", str)) return nrrdKernelC5SepticApproxInverse; |
2868 |
✗✓ | 186 |
if (!strcmp("gaussian", str)) return nrrdKernelGaussian; |
2869 |
✓✓ | 198 |
if (!strcmp("gauss", str)) return nrrdKernelGaussian; |
2870 |
✗✓ | 174 |
if (!strcmp("gaussiand", str)) return nrrdKernelGaussianD; |
2871 |
✓✓ | 186 |
if (!strcmp("gaussd", str)) return nrrdKernelGaussianD; |
2872 |
✗✓ | 162 |
if (!strcmp("gd", str)) return nrrdKernelGaussianD; |
2873 |
✗✓ | 162 |
if (!strcmp("gaussiandd", str)) return nrrdKernelGaussianDD; |
2874 |
✓✓ | 174 |
if (!strcmp("gaussdd", str)) return nrrdKernelGaussianDD; |
2875 |
✗✓ | 150 |
if (!strcmp("gdd", str)) return nrrdKernelGaussianDD; |
2876 |
✗✓ | 150 |
if (!strcmp("ds", str)) return nrrdKernelDiscreteGaussian; |
2877 |
✗✓ | 150 |
if (!strcmp("dscale", str)) return nrrdKernelDiscreteGaussian; |
2878 |
✓✓ | 159 |
if (!strcmp("dg", str)) return nrrdKernelDiscreteGaussian; |
2879 |
✗✓ | 141 |
if (!strcmp("dgauss", str)) return nrrdKernelDiscreteGaussian; |
2880 |
✗✓ | 141 |
if (!strcmp("dgaussian", str)) return nrrdKernelDiscreteGaussian; |
2881 |
✓✓ | 153 |
if (!strcmp("discretegauss", str)) return nrrdKernelDiscreteGaussian; |
2882 |
✓✓ | 141 |
if (!strcmp("hann", str)) return nrrdKernelHann; |
2883 |
✓✓ | 129 |
if (!strcmp("hannd", str)) return nrrdKernelHannD; |
2884 |
✓✓ | 117 |
if (!strcmp("hanndd", str)) return nrrdKernelHannDD; |
2885 |
✗✓ | 93 |
if (!strcmp("bkmn", str)) return nrrdKernelBlackman; |
2886 |
✗✓ | 93 |
if (!strcmp("black", str)) return nrrdKernelBlackman; |
2887 |
✓✓ | 105 |
if (!strcmp("blackman", str)) return nrrdKernelBlackman; |
2888 |
✗✓ | 81 |
if (!strcmp("bkmnd", str)) return nrrdKernelBlackmanD; |
2889 |
✗✓ | 81 |
if (!strcmp("blackd", str)) return nrrdKernelBlackmanD; |
2890 |
✓✓ | 93 |
if (!strcmp("blackmand", str)) return nrrdKernelBlackmanD; |
2891 |
✗✓ | 69 |
if (!strcmp("bkmndd", str)) return nrrdKernelBlackmanDD; |
2892 |
✗✓ | 69 |
if (!strcmp("blackdd", str)) return nrrdKernelBlackmanDD; |
2893 |
✓✓ | 81 |
if (!strcmp("blackmandd", str)) return nrrdKernelBlackmanDD; |
2894 |
✓✓ | 59 |
if (!strcmp("bspl1", str)) return nrrdKernelBSpline1; |
2895 |
✗✓ | 55 |
if (!strcmp("bspln1", str)) return nrrdKernelBSpline1; |
2896 |
✓✓ | 57 |
if (!strcmp("bspl1d", str)) return nrrdKernelBSpline1D; |
2897 |
✗✓ | 53 |
if (!strcmp("bspln1d", str)) return nrrdKernelBSpline1D; |
2898 |
✓✓ | 55 |
if (!strcmp("bspl2", str)) return nrrdKernelBSpline2; |
2899 |
✗✓ | 51 |
if (!strcmp("bspln2", str)) return nrrdKernelBSpline2; |
2900 |
✓✓ | 53 |
if (!strcmp("bspl2d", str)) return nrrdKernelBSpline2D; |
2901 |
✗✓ | 49 |
if (!strcmp("bspln2d", str)) return nrrdKernelBSpline2D; |
2902 |
✓✓ | 51 |
if (!strcmp("bspl2dd", str)) return nrrdKernelBSpline2DD; |
2903 |
✗✓ | 47 |
if (!strcmp("bspln2dd", str)) return nrrdKernelBSpline2DD; |
2904 |
✓✓ | 49 |
if (!strcmp("bspl3", str)) return nrrdKernelBSpline3; |
2905 |
✗✓ | 45 |
if (!strcmp("bspln3", str)) return nrrdKernelBSpline3; |
2906 |
✓✓ | 47 |
if (!strcmp("bspl3ai", str)) return nrrdKernelBSpline3ApproxInverse; |
2907 |
✗✓ | 43 |
if (!strcmp("bspln3ai", str)) return nrrdKernelBSpline3ApproxInverse; |
2908 |
✓✓ | 45 |
if (!strcmp("bspl3d", str)) return nrrdKernelBSpline3D; |
2909 |
✗✓ | 41 |
if (!strcmp("bspln3d", str)) return nrrdKernelBSpline3D; |
2910 |
✓✓ | 43 |
if (!strcmp("bspl3dd", str)) return nrrdKernelBSpline3DD; |
2911 |
✗✓ | 39 |
if (!strcmp("bspln3dd", str)) return nrrdKernelBSpline3DD; |
2912 |
✓✓ | 41 |
if (!strcmp("bspl3ddd", str)) return nrrdKernelBSpline3DDD; |
2913 |
✗✓ | 37 |
if (!strcmp("bspln3ddd", str)) return nrrdKernelBSpline3DDD; |
2914 |
✓✓ | 39 |
if (!strcmp("bspl4", str)) return nrrdKernelBSpline4; |
2915 |
✗✓ | 35 |
if (!strcmp("bspln4", str)) return nrrdKernelBSpline4; |
2916 |
✓✓ | 37 |
if (!strcmp("bspl4d", str)) return nrrdKernelBSpline4D; |
2917 |
✗✓ | 33 |
if (!strcmp("bspln4d", str)) return nrrdKernelBSpline4D; |
2918 |
✓✓ | 35 |
if (!strcmp("bspl4dd", str)) return nrrdKernelBSpline4DD; |
2919 |
✗✓ | 31 |
if (!strcmp("bspln4dd", str)) return nrrdKernelBSpline4DD; |
2920 |
✓✓ | 33 |
if (!strcmp("bspl4ddd", str)) return nrrdKernelBSpline4DDD; |
2921 |
✗✓ | 29 |
if (!strcmp("bspln4ddd", str)) return nrrdKernelBSpline4DDD; |
2922 |
✓✓ | 31 |
if (!strcmp("bspl5", str)) return nrrdKernelBSpline5; |
2923 |
✗✓ | 27 |
if (!strcmp("bspln5", str)) return nrrdKernelBSpline5; |
2924 |
✓✓ | 29 |
if (!strcmp("bspl5ai", str)) return nrrdKernelBSpline5ApproxInverse; |
2925 |
✗✓ | 25 |
if (!strcmp("bspln5ai", str)) return nrrdKernelBSpline5ApproxInverse; |
2926 |
✓✓ | 27 |
if (!strcmp("bspl5d", str)) return nrrdKernelBSpline5D; |
2927 |
✗✓ | 23 |
if (!strcmp("bspln5d", str)) return nrrdKernelBSpline5D; |
2928 |
✓✓ | 25 |
if (!strcmp("bspl5dd", str)) return nrrdKernelBSpline5DD; |
2929 |
✗✓ | 21 |
if (!strcmp("bspln5dd", str)) return nrrdKernelBSpline5DD; |
2930 |
✓✓ | 23 |
if (!strcmp("bspl5ddd", str)) return nrrdKernelBSpline5DDD; |
2931 |
✗✓ | 19 |
if (!strcmp("bspln5ddd", str)) return nrrdKernelBSpline5DDD; |
2932 |
✓✓ | 21 |
if (!strcmp("bspl6", str)) return nrrdKernelBSpline6; |
2933 |
✗✓ | 17 |
if (!strcmp("bspln6", str)) return nrrdKernelBSpline6; |
2934 |
✓✓ | 19 |
if (!strcmp("bspl6d", str)) return nrrdKernelBSpline6D; |
2935 |
✗✓ | 15 |
if (!strcmp("bspln6d", str)) return nrrdKernelBSpline6D; |
2936 |
✓✓ | 17 |
if (!strcmp("bspl6dd", str)) return nrrdKernelBSpline6DD; |
2937 |
✗✓ | 13 |
if (!strcmp("bspln6dd", str)) return nrrdKernelBSpline6DD; |
2938 |
✓✓ | 15 |
if (!strcmp("bspl6ddd", str)) return nrrdKernelBSpline6DDD; |
2939 |
✗✓ | 11 |
if (!strcmp("bspln6ddd", str)) return nrrdKernelBSpline6DDD; |
2940 |
✓✓ | 13 |
if (!strcmp("bspl7", str)) return nrrdKernelBSpline7; |
2941 |
✗✓ | 9 |
if (!strcmp("bspln7", str)) return nrrdKernelBSpline7; |
2942 |
✓✓ | 11 |
if (!strcmp("bspl7ai", str)) return nrrdKernelBSpline7ApproxInverse; |
2943 |
✗✓ | 7 |
if (!strcmp("bspln7ai", str)) return nrrdKernelBSpline7ApproxInverse; |
2944 |
✓✓ | 9 |
if (!strcmp("bspl7d", str)) return nrrdKernelBSpline7D; |
2945 |
✗✓ | 5 |
if (!strcmp("bspln7d", str)) return nrrdKernelBSpline7D; |
2946 |
✓✓ | 7 |
if (!strcmp("bspl7dd", str)) return nrrdKernelBSpline7DD; |
2947 |
✗✓ | 3 |
if (!strcmp("bspln7dd", str)) return nrrdKernelBSpline7DD; |
2948 |
✓✓ | 5 |
if (!strcmp("bspl7ddd", str)) return nrrdKernelBSpline7DDD; |
2949 |
✗✓ | 1 |
if (!strcmp("bspln7ddd", str)) return nrrdKernelBSpline7DDD; |
2950 |
1 |
return NULL; |
|
2951 |
370 |
} |
|
2952 |
|||
2953 |
/* this returns a number between -1 and max; |
||
2954 |
it does NOT do the increment-by-one; |
||
2955 |
it does NOT do range checking */ |
||
2956 |
int |
||
2957 |
_nrrdKernelParseTMFInt(int *val, char *str) { |
||
2958 |
static const char me[]="nrrdKernelParseTMFInt"; |
||
2959 |
|||
2960 |
✓✓ | 1920 |
if (!strcmp("n", str)) { |
2961 |
144 |
*val = -1; |
|
2962 |
144 |
} else { |
|
2963 |
✗✓ | 816 |
if (1 != sscanf(str, "%d", val)) { |
2964 |
biffAddf(NRRD, "%s: couldn't parse \"%s\" as int", me, str); |
||
2965 |
return 1; |
||
2966 |
} |
||
2967 |
} |
||
2968 |
960 |
return 0; |
|
2969 |
960 |
} |
|
2970 |
|||
2971 |
int |
||
2972 |
nrrdKernelParse(const NrrdKernel **kernelP, |
||
2973 |
double *parm, const char *_str) { |
||
2974 |
static const char me[]="nrrdKernelParse"; |
||
2975 |
1380 |
char str[AIR_STRLEN_HUGE], |
|
2976 |
kstr[AIR_STRLEN_MED], *_pstr=NULL, *pstr, |
||
2977 |
690 |
*tmfStr[4] = {NULL, NULL, NULL, NULL}; |
|
2978 |
690 |
int tmfD, tmfC, tmfA; |
|
2979 |
unsigned int jj, haveParm, needParm; |
||
2980 |
airArray *mop; |
||
2981 |
|||
2982 |
✗✓ | 690 |
if (!(kernelP && parm && _str)) { |
2983 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
2984 |
return 1; |
||
2985 |
} |
||
2986 |
|||
2987 |
/* [jorik] (if i understood this correctly) parm is always of length |
||
2988 |
** NRRD_KERNEL_PARMS_NUM. We have to clear all parameters here, since |
||
2989 |
** nrrdKernelSet copies all arguments into its own array later, and |
||
2990 |
** copying uninitialised memory is bad (it traps my memory debugger). |
||
2991 |
*/ |
||
2992 |
✓✓ | 12420 |
for (jj=0; jj<NRRD_KERNEL_PARMS_NUM; jj++) { |
2993 |
5520 |
parm[jj] = 0; |
|
2994 |
} |
||
2995 |
|||
2996 |
690 |
airStrcpy(str, AIR_STRLEN_HUGE, _str); |
|
2997 |
690 |
strcpy(kstr, ""); |
|
2998 |
pstr = NULL; |
||
2999 |
690 |
pstr = strchr(str, ':'); |
|
3000 |
✓✓ | 690 |
if (pstr) { |
3001 |
577 |
*pstr = '\0'; |
|
3002 |
577 |
_pstr = ++pstr; |
|
3003 |
577 |
} |
|
3004 |
690 |
strcpy(kstr, str); |
|
3005 |
690 |
airToLower(kstr); |
|
3006 |
690 |
mop = airMopNew(); |
|
3007 |
/* first see if its a TMF, then try parsing it as the other stuff */ |
||
3008 |
✓✓ | 690 |
if (kstr == strstr(kstr, "tmf")) { |
3009 |
✓✓ | 320 |
if (4 == airParseStrS(tmfStr, pstr, ",", 4)) { |
3010 |
160 |
airMopAdd(mop, tmfStr[0], airFree, airMopAlways); |
|
3011 |
160 |
airMopAdd(mop, tmfStr[1], airFree, airMopAlways); |
|
3012 |
160 |
airMopAdd(mop, tmfStr[2], airFree, airMopAlways); |
|
3013 |
160 |
airMopAdd(mop, tmfStr[3], airFree, airMopAlways); |
|
3014 |
/* a TMF with a parameter: D,C,A,a */ |
||
3015 |
✗✓ | 160 |
if (1 != airSingleSscanf(tmfStr[3], "%lg", parm)) { |
3016 |
biffAddf(NRRD, "%s: couldn't parse TMF parameter \"%s\" as double", |
||
3017 |
me, tmfStr[3]); |
||
3018 |
airMopError(mop); return 1; |
||
3019 |
} |
||
3020 |
✓✗ | 160 |
} else if (3 == airParseStrS(tmfStr, pstr, ",", 3)) { |
3021 |
160 |
airMopAdd(mop, tmfStr[0], airFree, airMopAlways); |
|
3022 |
160 |
airMopAdd(mop, tmfStr[1], airFree, airMopAlways); |
|
3023 |
160 |
airMopAdd(mop, tmfStr[2], airFree, airMopAlways); |
|
3024 |
/* a TMF without a parameter: D,C,A ==> a=0.0 */ |
||
3025 |
160 |
parm[0] = 0.0; |
|
3026 |
} else { |
||
3027 |
biffAddf(NRRD, "%s: TMF kernels require 3 arguments D, C, A " |
||
3028 |
"in the form tmf:D,C,A", me); |
||
3029 |
airMopError(mop); return 1; |
||
3030 |
} |
||
3031 |
✗✓ | 640 |
if (_nrrdKernelParseTMFInt(&tmfD, tmfStr[0]) |
3032 |
✓✗ | 640 |
|| _nrrdKernelParseTMFInt(&tmfC, tmfStr[1]) |
3033 |
✓✗ | 640 |
|| _nrrdKernelParseTMFInt(&tmfA, tmfStr[2])) { |
3034 |
biffAddf(NRRD, "%s: problem parsing \"%s,%s,%s\" as D,C,A " |
||
3035 |
"for TMF kernel", me, tmfStr[0], tmfStr[1], tmfStr[2]); |
||
3036 |
airMopError(mop); return 1; |
||
3037 |
} |
||
3038 |
✓✗✗✓ |
640 |
if (!AIR_IN_CL(-1, tmfD, (int)nrrdKernelTMF_maxD)) { |
3039 |
biffAddf(NRRD, "%s: derivative value %d outside range [-1,%d]", |
||
3040 |
me, tmfD, nrrdKernelTMF_maxD); |
||
3041 |
airMopError(mop); return 1; |
||
3042 |
} |
||
3043 |
✓✗✗✓ |
640 |
if (!AIR_IN_CL(-1, tmfC, (int)nrrdKernelTMF_maxC)) { |
3044 |
biffAddf(NRRD, "%s: continuity value %d outside range [-1,%d]", |
||
3045 |
me, tmfC, nrrdKernelTMF_maxC); |
||
3046 |
airMopError(mop); return 1; |
||
3047 |
} |
||
3048 |
✓✗✗✓ |
640 |
if (!AIR_IN_CL(1, tmfA, (int)nrrdKernelTMF_maxA)) { |
3049 |
biffAddf(NRRD, "%s: accuracy value %d outside range [1,%d]", |
||
3050 |
me, tmfA, nrrdKernelTMF_maxA); |
||
3051 |
airMopError(mop); return 1; |
||
3052 |
} |
||
3053 |
/* |
||
3054 |
fprintf(stderr, "!%s: D,C,A = %d,%d,%d --> %d,%d,%d\n", me, |
||
3055 |
tmfD, tmfC, tmfA, tmfD+1, tmfC+1, tmfA); |
||
3056 |
*/ |
||
3057 |
320 |
*kernelP = nrrdKernelTMF[tmfD+1][tmfC+1][tmfA]; |
|
3058 |
320 |
} else { |
|
3059 |
/* its not a TMF */ |
||
3060 |
✓✓ | 370 |
if (!(*kernelP = _nrrdKernelStrToKern(kstr))) { |
3061 |
1 |
biffAddf(NRRD, "%s: kernel \"%s\" not recognized", me, kstr); |
|
3062 |
1 |
airMopError(mop); return 1; |
|
3063 |
} |
||
3064 |
✗✓ | 369 |
if ((*kernelP)->numParm > NRRD_KERNEL_PARMS_NUM) { |
3065 |
biffAddf(NRRD, "%s: kernel \"%s\" requests %d parameters > max %d", |
||
3066 |
me, kstr, (*kernelP)->numParm, NRRD_KERNEL_PARMS_NUM); |
||
3067 |
airMopError(mop); return 1; |
||
3068 |
} |
||
3069 |
✓✓✓✓ |
665 |
if (*kernelP == nrrdKernelGaussian || |
3070 |
✓✓ | 357 |
*kernelP == nrrdKernelGaussianD || |
3071 |
✓✓ | 345 |
*kernelP == nrrdKernelGaussianDD || |
3072 |
✓✓ | 333 |
*kernelP == nrrdKernelDiscreteGaussian || |
3073 |
✓✓ | 312 |
*kernelP == nrrdKernelBoxSupportDebug || |
3074 |
✓✓ | 308 |
*kernelP == nrrdKernelCos4SupportDebug || |
3075 |
✓✓ | 304 |
*kernelP == nrrdKernelCos4SupportDebugD || |
3076 |
✓✓ | 300 |
*kernelP == nrrdKernelCos4SupportDebugDD || |
3077 |
296 |
*kernelP == nrrdKernelCos4SupportDebugDDD) { |
|
3078 |
/* for these kernels, we need all the parameters given explicitly */ |
||
3079 |
77 |
needParm = (*kernelP)->numParm; |
|
3080 |
77 |
} else { |
|
3081 |
/* For everything else (note that TMF kernels are handled |
||
3082 |
separately), we can make do with one less than the required, |
||
3083 |
by using the default spacing */ |
||
3084 |
✓✓ | 764 |
needParm = ((*kernelP)->numParm > 0 |
3085 |
180 |
? (*kernelP)->numParm - 1 |
|
3086 |
: 0); |
||
3087 |
} |
||
3088 |
✗✓ | 369 |
if (needParm > 0 && !pstr) { |
3089 |
biffAddf(NRRD, "%s: didn't get any of %d required doubles after " |
||
3090 |
"colon in \"%s\"", |
||
3091 |
me, needParm, kstr); |
||
3092 |
airMopError(mop); return 1; |
||
3093 |
} |
||
3094 |
✓✓✓✓ |
2625 |
for (haveParm=0; haveParm<(*kernelP)->numParm; haveParm++) { |
3095 |
875 |
if (!pstr) |
|
3096 |
break; |
||
3097 |
✗✓ | 506 |
if (1 != airSingleSscanf(pstr, "%lg", parm+haveParm)) { |
3098 |
biffAddf(NRRD, "%s: trouble parsing \"%s\" as double (in \"%s\")", |
||
3099 |
me, _pstr, _str); |
||
3100 |
airMopError(mop); return 1; |
||
3101 |
} |
||
3102 |
✓✓ | 506 |
if ((pstr = strchr(pstr, ','))) { |
3103 |
249 |
pstr++; |
|
3104 |
✗✓ | 249 |
if (!*pstr) { |
3105 |
biffAddf(NRRD, "%s: nothing after last comma in \"%s\" (in \"%s\")", |
||
3106 |
me, _pstr, _str); |
||
3107 |
airMopError(mop); return 1; |
||
3108 |
} |
||
3109 |
} |
||
3110 |
} |
||
3111 |
/* haveParm is now the number of parameters that were parsed. */ |
||
3112 |
✗✓ | 369 |
if (haveParm < needParm) { |
3113 |
biffAddf(NRRD, "%s: parsed only %d of %d required doubles " |
||
3114 |
"from \"%s\" (in \"%s\")", |
||
3115 |
me, haveParm, needParm, _pstr, _str); |
||
3116 |
airMopError(mop); return 1; |
||
3117 |
✓✓✗✓ |
558 |
} else if (haveParm == needParm && |
3118 |
189 |
needParm == (*kernelP)->numParm-1) { |
|
3119 |
/* shift up parsed values, and set parm[0] to default */ |
||
3120 |
for (jj=haveParm; jj>=1; jj--) { |
||
3121 |
parm[jj] = parm[jj-1]; |
||
3122 |
} |
||
3123 |
parm[0] = nrrdDefaultKernelParm0; |
||
3124 |
} else { |
||
3125 |
✗✓ | 369 |
if (pstr) { |
3126 |
biffAddf(NRRD, "%s: \"%s\" (in \"%s\") has more than %d doubles", |
||
3127 |
me, _pstr, _str, (*kernelP)->numParm); |
||
3128 |
airMopError(mop); return 1; |
||
3129 |
} |
||
3130 |
} |
||
3131 |
} |
||
3132 |
/* |
||
3133 |
fprintf(stderr, "%s: %g %g %g %g %g\n", me, |
||
3134 |
parm[0], parm[1], parm[2], parm[3], parm[4]); |
||
3135 |
*/ |
||
3136 |
689 |
airMopOkay(mop); |
|
3137 |
689 |
return 0; |
|
3138 |
690 |
} |
|
3139 |
|||
3140 |
int |
||
3141 |
nrrdKernelSpecParse(NrrdKernelSpec *ksp, const char *str) { |
||
3142 |
static const char me[]="nrrdKernelSpecParse"; |
||
3143 |
700 |
const NrrdKernel *kern; |
|
3144 |
350 |
double kparm[NRRD_KERNEL_PARMS_NUM]; |
|
3145 |
|||
3146 |
✗✓ | 350 |
if (!( ksp && str )) { |
3147 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
3148 |
return 1; |
||
3149 |
} |
||
3150 |
✓✓ | 350 |
if (nrrdKernelParse(&kern, kparm, str)) { |
3151 |
1 |
biffAddf(NRRD, "%s: ", me); |
|
3152 |
1 |
return 1; |
|
3153 |
} |
||
3154 |
349 |
nrrdKernelSpecSet(ksp, kern, kparm); |
|
3155 |
349 |
return 0; |
|
3156 |
350 |
} |
|
3157 |
|||
3158 |
/* |
||
3159 |
** note that the given string has to be allocated for a certain size |
||
3160 |
** which is plenty big |
||
3161 |
*/ |
||
3162 |
int |
||
3163 |
nrrdKernelSpecSprint(char str[AIR_STRLEN_LARGE], const NrrdKernelSpec *ksp) { |
||
3164 |
static const char me[]="nrrdKernelSpecSprint"; |
||
3165 |
unsigned int warnLen = AIR_STRLEN_LARGE/3; |
||
3166 |
1364 |
char stmp[AIR_STRLEN_LARGE]; |
|
3167 |
|||
3168 |
✗✓ | 682 |
if (!( str && ksp )) { |
3169 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
3170 |
return 1; |
||
3171 |
} |
||
3172 |
✗✓ | 682 |
if (strlen(ksp->kernel->name) > warnLen) { |
3173 |
biffAddf(NRRD, "%s: kernel name (len %s) might lead to overflow", me, |
||
3174 |
airSprintSize_t(stmp, strlen(ksp->kernel->name))); |
||
3175 |
return 1; |
||
3176 |
} |
||
3177 |
✓✓ | 682 |
if (strstr(ksp->kernel->name, "TMF")) { |
3178 |
/* these are handled differently; the identification of the |
||
3179 |
kernel is actually packaged as kernel parameters */ |
||
3180 |
✗✓ | 320 |
if (!(ksp->kernel->name == strstr(ksp->kernel->name, "TMF"))) { |
3181 |
biffAddf(NRRD, "%s: TMF kernel name %s didn't start with TMF", |
||
3182 |
me, ksp->kernel->name); |
||
3183 |
return 1; |
||
3184 |
} |
||
3185 |
/* 0123456789012 */ |
||
3186 |
/* TMF_dX_cX_Xef */ |
||
3187 |
✗✓ | 640 |
if (!( 13 == strlen(ksp->kernel->name) |
3188 |
✓✗ | 640 |
&& '_' == ksp->kernel->name[3] |
3189 |
✓✗ | 640 |
&& '_' == ksp->kernel->name[6] |
3190 |
✓✗ | 640 |
&& '_' == ksp->kernel->name[9] )) { |
3191 |
biffAddf(NRRD, "%s: sorry, expected strlen(%s) = 13 with 3 _s", |
||
3192 |
me, ksp->kernel->name); |
||
3193 |
return 1; |
||
3194 |
} |
||
3195 |
320 |
sprintf(str, "tmf:%c,%c,%c", |
|
3196 |
ksp->kernel->name[5], |
||
3197 |
ksp->kernel->name[8], |
||
3198 |
ksp->kernel->name[10]); |
||
3199 |
/* see if the single parm should be added on */ |
||
3200 |
✓✓ | 320 |
if (0.0 != ksp->parm[0]) { |
3201 |
160 |
sprintf(stmp, ",%.17g", ksp->parm[0]); |
|
3202 |
160 |
strcat(str, stmp); |
|
3203 |
160 |
} |
|
3204 |
} else { |
||
3205 |
362 |
strcpy(str, ksp->kernel->name); |
|
3206 |
✓✓ | 362 |
if (ksp->kernel->numParm) { |
3207 |
unsigned int pi; |
||
3208 |
✓✓ | 1484 |
for (pi=0; pi<ksp->kernel->numParm; pi++) { |
3209 |
492 |
sprintf(stmp, "%c%.17g", (!pi ? ':' : ','), ksp->parm[pi]); |
|
3210 |
✗✓ | 492 |
if (strlen(str) + strlen(stmp) > warnLen) { |
3211 |
biffAddf(NRRD, "%s: kernel parm %u could overflow", me, pi); |
||
3212 |
return 1; |
||
3213 |
} |
||
3214 |
492 |
strcat(str, stmp); |
|
3215 |
} |
||
3216 |
250 |
} |
|
3217 |
} |
||
3218 |
682 |
return 0; |
|
3219 |
682 |
} |
|
3220 |
|||
3221 |
int |
||
3222 |
nrrdKernelSprint(char str[AIR_STRLEN_LARGE], const NrrdKernel *kernel, |
||
3223 |
const double kparm[NRRD_KERNEL_PARMS_NUM]) { |
||
3224 |
static const char me[]="nrrdKernelSprint"; |
||
3225 |
680 |
NrrdKernelSpec ksp; |
|
3226 |
|||
3227 |
340 |
nrrdKernelSpecSet(&ksp, kernel, kparm); |
|
3228 |
✗✓ | 340 |
if (nrrdKernelSpecSprint(str, &ksp)) { |
3229 |
biffAddf(NRRD, "%s: trouble", me); |
||
3230 |
return 1; |
||
3231 |
} |
||
3232 |
340 |
return 0; |
|
3233 |
340 |
} |
|
3234 |
|||
3235 |
/* |
||
3236 |
** This DOES make an effort to set *differ based on "ordering" (-1 or +1) |
||
3237 |
** but HEY that's very contrived; why bother? |
||
3238 |
*/ |
||
3239 |
int |
||
3240 |
nrrdKernelCompare(const NrrdKernel *kernA, |
||
3241 |
const double parmA[NRRD_KERNEL_PARMS_NUM], |
||
3242 |
const NrrdKernel *kernB, |
||
3243 |
const double parmB[NRRD_KERNEL_PARMS_NUM], |
||
3244 |
int *differ, char explain[AIR_STRLEN_LARGE]) { |
||
3245 |
static const char me[]="nrrdKernelCompare"; |
||
3246 |
unsigned int pnum, pidx; |
||
3247 |
|||
3248 |
✗✓ | 1364 |
if (!(kernA && kernB && differ)) { |
3249 |
biffAddf(NRRD, "%s: got NULL pointer (%p, %p, or %p)", me, |
||
3250 |
AIR_CVOIDP(kernA), AIR_CVOIDP(kernB), AIR_VOIDP(differ)); |
||
3251 |
return 1; |
||
3252 |
} |
||
3253 |
✗✓ | 682 |
if (kernA != kernB) { |
3254 |
*differ = kernA < kernB ? -1 : 1; |
||
3255 |
if (explain) { |
||
3256 |
sprintf(explain, "kernA %s kernB", *differ < 0 ? "<" : ">"); |
||
3257 |
} |
||
3258 |
return 0; |
||
3259 |
} |
||
3260 |
682 |
pnum = kernA->numParm; |
|
3261 |
✓✓ | 682 |
if (!pnum) { |
3262 |
/* actually, we're done: no parms and kernels are equal */ |
||
3263 |
112 |
*differ = 0; |
|
3264 |
112 |
return 0; |
|
3265 |
} |
||
3266 |
✗✓ | 570 |
if (!(parmA && parmB)) { |
3267 |
biffAddf(NRRD, "%s: kernel %s needs %u parms but got NULL parm vectors", |
||
3268 |
me, kernA->name ? kernA->name : "(unnamed)", pnum); |
||
3269 |
return 0; |
||
3270 |
} |
||
3271 |
✓✓ | 2764 |
for (pidx=0; pidx<pnum; pidx++) { |
3272 |
✗✓ | 812 |
if (parmA[pidx] != parmB[pidx]) { |
3273 |
*differ = parmA[pidx] < parmB[pidx] ? -1 : 1; |
||
3274 |
if (explain) { |
||
3275 |
sprintf(explain, "parmA[%u]=%f %s parmB[%u]=%f", pidx, parmA[pidx], |
||
3276 |
*differ < 0 ? "<" : ">", pidx, parmB[pidx]); |
||
3277 |
} |
||
3278 |
return 0; |
||
3279 |
} |
||
3280 |
} |
||
3281 |
|||
3282 |
/* so far nothing unequal */ |
||
3283 |
570 |
*differ = 0; |
|
3284 |
570 |
return 0; |
|
3285 |
682 |
} |
|
3286 |
|||
3287 |
/* |
||
3288 |
** This DOES NOT make an effort to set *differ based on "ordering"; |
||
3289 |
*/ |
||
3290 |
int |
||
3291 |
nrrdKernelSpecCompare(const NrrdKernelSpec *aa, |
||
3292 |
const NrrdKernelSpec *bb, |
||
3293 |
int *differ, char explain[AIR_STRLEN_LARGE]) { |
||
3294 |
static const char me[]="nrrdKernelSpecCompare"; |
||
3295 |
10 |
char subexplain[AIR_STRLEN_LARGE]; |
|
3296 |
|||
3297 |
✗✓ | 5 |
if (!( differ )) { |
3298 |
biffAddf(NRRD, "%s: got NULL differ", me); |
||
3299 |
return 1; |
||
3300 |
} |
||
3301 |
✗✓ | 5 |
if (!!aa != !!bb) { |
3302 |
if (explain) { |
||
3303 |
sprintf(explain, "different NULL-ities of kspec itself %s != %s", |
||
3304 |
aa ? "non-NULL" : "NULL", |
||
3305 |
bb ? "non-NULL" : "NULL"); |
||
3306 |
} |
||
3307 |
*differ = 1; return 0; |
||
3308 |
} |
||
3309 |
✓✓ | 5 |
if (!aa) { |
3310 |
/* got two NULL kernel specs ==> equal */ |
||
3311 |
3 |
*differ = 0; return 0; |
|
3312 |
} |
||
3313 |
✗✓ | 2 |
if (!!aa->kernel != !!bb->kernel) { |
3314 |
if (explain) { |
||
3315 |
sprintf(explain, "different NULL-ities of kspec->kernel %s != %s", |
||
3316 |
aa->kernel ? "non-NULL" : "NULL", |
||
3317 |
bb->kernel ? "non-NULL" : "NULL"); |
||
3318 |
} |
||
3319 |
*differ = 1; return 0; |
||
3320 |
} |
||
3321 |
✗✓ | 2 |
if (!aa->kernel) { |
3322 |
/* both kernels NULL, can't do anything informative with parms */ |
||
3323 |
*differ = 0; return 0; |
||
3324 |
} |
||
3325 |
✗✓✗✓ |
4 |
if (nrrdKernelCompare(aa->kernel, aa->parm, |
3326 |
2 |
bb->kernel, bb->parm, |
|
3327 |
2 |
differ, subexplain)) { |
|
3328 |
biffAddf(NRRD, "%s: trouble comparing kernels", me); |
||
3329 |
return 1; |
||
3330 |
} |
||
3331 |
✗✓ | 2 |
if (*differ) { |
3332 |
if (explain) { |
||
3333 |
sprintf(explain, "kern/parm pairs differ: %s", subexplain); |
||
3334 |
} |
||
3335 |
*differ = 1; /* losing ordering info (of dubious value) */ |
||
3336 |
return 0; |
||
3337 |
} |
||
3338 |
2 |
*differ = 0; |
|
3339 |
2 |
return 0; |
|
3340 |
5 |
} |
|
3341 |
|||
3342 |
/* |
||
3343 |
******** nrrdKernelCheck |
||
3344 |
** |
||
3345 |
** Makes sure a given kernel is behaving as expected |
||
3346 |
** |
||
3347 |
** Tests: |
||
3348 |
** nrrdKernelSprint |
||
3349 |
** nrrdKernelParse |
||
3350 |
** nrrdKernelCompare |
||
3351 |
** nrrdKernelSpecNew |
||
3352 |
** nrrdKernelSpecNix |
||
3353 |
** nrrdKernelSpecSet |
||
3354 |
** nrrdKernelSpecSprint |
||
3355 |
** nrrdKernelSpecParse |
||
3356 |
** and also exercises all the ways of evaluating the kernel and |
||
3357 |
** makes sure they all agree, and agree with the integral kernel, if given |
||
3358 |
*/ |
||
3359 |
int |
||
3360 |
nrrdKernelCheck(const NrrdKernel *kern, |
||
3361 |
const double parm[NRRD_KERNEL_PARMS_NUM], |
||
3362 |
size_t evalNum, double epsilon, |
||
3363 |
unsigned int diffOkEvalMax, |
||
3364 |
unsigned int diffOkIntglMax, |
||
3365 |
const NrrdKernel *ikern, |
||
3366 |
const double iparm[NRRD_KERNEL_PARMS_NUM]) { |
||
3367 |
680 |
const NrrdKernel *parsedkern; |
|
3368 |
340 |
double parsedparm[NRRD_KERNEL_PARMS_NUM], supp, integral; |
|
3369 |
static const char me[]="nrrdKernelCheck"; |
||
3370 |
340 |
char kstr[AIR_STRLEN_LARGE], kspstr[AIR_STRLEN_LARGE], |
|
3371 |
explain[AIR_STRLEN_LARGE], stmp[AIR_STRLEN_SMALL]; |
||
3372 |
340 |
int differ; |
|
3373 |
size_t evalIdx; |
||
3374 |
double *dom_d, *ran_d, wee; |
||
3375 |
float *dom_f, *ran_f; |
||
3376 |
unsigned int diffOkEvalNum, diffOkIntglNum; |
||
3377 |
NrrdKernelSpec *kspA, *kspB; |
||
3378 |
airArray *mop; |
||
3379 |
|||
3380 |
340 |
mop = airMopNew(); |
|
3381 |
✗✓ | 340 |
if (!kern) { |
3382 |
biffAddf(NRRD, "%s: got NULL kernel", me); |
||
3383 |
airMopError(mop); return 1; |
||
3384 |
} |
||
3385 |
✗✓ | 340 |
if (!(evalNum > 20)) { |
3386 |
biffAddf(NRRD, "%s: need evalNum > 20", me); |
||
3387 |
airMopError(mop); return 1; |
||
3388 |
} |
||
3389 |
✓✗✗✓ |
1020 |
if (!(kern->support && kern->integral |
3390 |
✓✗✓✗ |
1020 |
&& kern->eval1_f && kern->evalN_f |
3391 |
✓✗✓✗ |
1020 |
&& kern->eval1_d && kern->evalN_d)) { |
3392 |
biffAddf(NRRD, "%s: kernel has NULL fields (%d,%d,%d,%d,%d,%d)", me, |
||
3393 |
!!(kern->support), !!(kern->integral), |
||
3394 |
!!(kern->eval1_f), !!(kern->evalN_f), |
||
3395 |
!!(kern->eval1_d), !!(kern->evalN_d)); |
||
3396 |
airMopError(mop); return 1; |
||
3397 |
} |
||
3398 |
340 |
kspA = nrrdKernelSpecNew(); |
|
3399 |
340 |
airMopAdd(mop, kspA, (airMopper)nrrdKernelSpecNix, airMopAlways); |
|
3400 |
340 |
kspB = nrrdKernelSpecNew(); |
|
3401 |
340 |
airMopAdd(mop, kspB, (airMopper)nrrdKernelSpecNix, airMopAlways); |
|
3402 |
340 |
nrrdKernelSpecSet(kspA, kern, parm); |
|
3403 |
✗✓ | 680 |
if (nrrdKernelSprint(kstr, kern, parm) |
3404 |
✓✗ | 680 |
|| nrrdKernelSpecSprint(kspstr, kspA)) { |
3405 |
biffAddf(NRRD, "%s: trouble", me); |
||
3406 |
airMopError(mop); return 1; |
||
3407 |
} |
||
3408 |
✗✓ | 340 |
if (strcmp(kstr, kspstr)) { |
3409 |
biffAddf(NRRD, "%s: sprinted kernel |%s| != kspec |%s|", me, kstr, kspstr); |
||
3410 |
airMopError(mop); return 1; |
||
3411 |
} |
||
3412 |
✗✓ | 680 |
if (nrrdKernelParse(&parsedkern, parsedparm, kstr) |
3413 |
✓✗ | 680 |
|| nrrdKernelSpecParse(kspB, kstr)) { |
3414 |
biffAddf(NRRD, "%s: trouble parsing |%s| back to kern/parm pair or kspec", |
||
3415 |
me, kstr); |
||
3416 |
airMopError(mop); return 1; |
||
3417 |
} |
||
3418 |
✗✓✗✓ |
680 |
if (nrrdKernelCompare(kern, parm, parsedkern, parsedparm, |
3419 |
340 |
&differ, explain)) { |
|
3420 |
biffAddf(NRRD, "%s: trouble comparing kern/parm pairs", me); |
||
3421 |
airMopError(mop); return 1; |
||
3422 |
} |
||
3423 |
✗✓ | 340 |
if (differ) { |
3424 |
biffAddf(NRRD, "%s: given and re-parsed kernels differ: %s", me, explain); |
||
3425 |
airMopError(mop); return 1; |
||
3426 |
} |
||
3427 |
✗✓✗✓ |
680 |
if (nrrdKernelCompare(kspA->kernel, kspA->parm, |
3428 |
340 |
kspB->kernel, kspB->parm, |
|
3429 |
&differ, explain)) { |
||
3430 |
biffAddf(NRRD, "%s: trouble comparing kspecs", me); |
||
3431 |
airMopError(mop); return 1; |
||
3432 |
} |
||
3433 |
✗✓ | 340 |
if (differ) { |
3434 |
biffAddf(NRRD, "%s: given and re-parsed kspecs differ: %s", me, explain); |
||
3435 |
airMopError(mop); return 1; |
||
3436 |
} |
||
3437 |
|||
3438 |
340 |
supp = kern->support(parm); |
|
3439 |
/* wee is the step between evaluation points */ |
||
3440 |
340 |
wee = 2*supp/AIR_CAST(double, evalNum); |
|
3441 |
✓✓✗✓ |
678 |
if ( (kern->eval1_d)(supp+wee/1000, parm) || |
3442 |
✓✗ | 338 |
(kern->eval1_d)(supp+wee, parm) || |
3443 |
✓✗ | 338 |
(kern->eval1_d)(supp+10*wee, parm) || |
3444 |
✓✗ | 338 |
(kern->eval1_d)(-supp-wee/1000, parm) || |
3445 |
✓✗ | 338 |
(kern->eval1_d)(-supp-wee, parm) || |
3446 |
338 |
(kern->eval1_d)(-supp-10*wee, parm) ) { |
|
3447 |
✗✓ | 2 |
if (nrrdKernelCheap != kern) { |
3448 |
/* the "cheap" kernel alone gets a pass on reporting its support */ |
||
3449 |
biffAddf(NRRD, "%s: kern %s is non-zero outside support %g", |
||
3450 |
me, kstr, supp); |
||
3451 |
airMopError(mop); return 1; |
||
3452 |
} |
||
3453 |
} |
||
3454 |
/* allocate domain and range for both float and double */ |
||
3455 |
340 |
dom_d = AIR_CALLOC(evalNum, double); |
|
3456 |
340 |
airMopAdd(mop, dom_d, airFree, airMopAlways); |
|
3457 |
340 |
ran_d = AIR_CALLOC(evalNum, double); |
|
3458 |
340 |
airMopAdd(mop, ran_d, airFree, airMopAlways); |
|
3459 |
340 |
dom_f = AIR_CALLOC(evalNum, float); |
|
3460 |
340 |
airMopAdd(mop, dom_f, airFree, airMopAlways); |
|
3461 |
340 |
ran_f = AIR_CALLOC(evalNum, float); |
|
3462 |
340 |
airMopAdd(mop, ran_f, airFree, airMopAlways); |
|
3463 |
✗✓ | 340 |
if (!( dom_d && ran_d && dom_f && ran_f )) { |
3464 |
biffAddf(NRRD, "%s: couldn't alloc buffers for %s values for %s", |
||
3465 |
me, airSprintSize_t(stmp, evalNum), kstr); |
||
3466 |
airMopError(mop); return 1; |
||
3467 |
} |
||
3468 |
✓✓ | 81600680 |
for (evalIdx=0; evalIdx<evalNum; evalIdx++) { |
3469 |
40800000 |
dom_d[evalIdx] = AIR_AFFINE(-0.5, evalIdx, |
|
3470 |
AIR_CAST(double, evalNum)-0.5, |
||
3471 |
-supp, supp); |
||
3472 |
40800000 |
dom_f[evalIdx] = AIR_CAST(float, dom_d[evalIdx]); |
|
3473 |
} |
||
3474 |
/* do the vector evaluations */ |
||
3475 |
340 |
kern->evalN_f(ran_f, dom_f, evalNum, parm); |
|
3476 |
340 |
kern->evalN_d(ran_d, dom_d, evalNum, parm); |
|
3477 |
/* |
||
3478 |
for (evalIdx=0; evalIdx<evalNum; evalIdx++) { |
||
3479 |
fprintf(stderr, "%u %g --> %g\n", AIR_CAST(unsigned int, evalIdx), |
||
3480 |
dom_d[evalIdx], ran_d[evalIdx]); |
||
3481 |
} |
||
3482 |
*/ |
||
3483 |
/* compare evaluations (and maybe derivatives) and numerically compute |
||
3484 |
integral */ |
||
3485 |
diffOkEvalNum = 0; |
||
3486 |
diffOkIntglNum = 0; |
||
3487 |
integral = 0.0; |
||
3488 |
✓✓ | 81600680 |
for (evalIdx=0; evalIdx<evalNum; evalIdx++) { |
3489 |
double single_f, single_d; |
||
3490 |
40800000 |
single_f = kern->eval1_f(dom_f[evalIdx], parm); |
|
3491 |
40800000 |
single_d = kern->eval1_d(dom_d[evalIdx], parm); |
|
3492 |
40800000 |
integral += single_d; |
|
3493 |
/* single float vs vector float */ |
||
3494 |
✓✓ | 79440000 |
if (nrrdKernelForwDiff == kern |
3495 |
✓✓ | 81360000 |
|| nrrdKernelBCCubic == kern |
3496 |
✓✓ | 80160000 |
|| nrrdKernelBCCubicDD == kern |
3497 |
✓✓ | 78240000 |
|| nrrdKernelAQuarticDD == kern) { |
3498 |
/* HEY this is crazy: need a special epsilon for these kernels; |
||
3499 |
WHY WHY do these kernels evaluate to different things in the |
||
3500 |
single versus the vector case? */ |
||
3501 |
float specEps; |
||
3502 |
✓✓ | 2640000 |
if (nrrdKernelForwDiff == kern) { |
3503 |
specEps = 5e-9f; |
||
3504 |
✓✓ | 2640000 |
} else if (nrrdKernelBCCubic == kern) { |
3505 |
specEps = 5e-8f; |
||
3506 |
✓✓ | 2400000 |
} else if (nrrdKernelBCCubicDD == kern) { |
3507 |
specEps = 5e-8f; |
||
3508 |
✓✗ | 1440000 |
} else if (nrrdKernelAQuarticDD == kern) { |
3509 |
specEps = 5e-8f; |
||
3510 |
480000 |
} else { |
|
3511 |
specEps = 0.0; |
||
3512 |
} |
||
3513 |
✗✓ | 2640000 |
if (fabs(single_f - ran_f[evalIdx]) > specEps) { |
3514 |
biffAddf(NRRD, "%s: %s (eval1_f(%.17g)=%.17g) != " |
||
3515 |
"(evalN_f(%.17g)=%.17g) by %.17g > %.17g", |
||
3516 |
me, kstr, dom_f[evalIdx], single_f, |
||
3517 |
dom_f[evalIdx], ran_f[evalIdx], |
||
3518 |
fabs(single_f - ran_f[evalIdx]), specEps); |
||
3519 |
airMopError(mop); return 1; |
||
3520 |
} |
||
3521 |
2640000 |
} else { |
|
3522 |
✗✓ | 38160000 |
if (single_f != ran_f[evalIdx]) { |
3523 |
biffAddf(NRRD, "%s: %s (eval1_f(%.17g)=%.17g) != " |
||
3524 |
"(evalN_f(%.17g)=%.17g)", |
||
3525 |
me, kstr, dom_f[evalIdx], single_f, |
||
3526 |
dom_f[evalIdx], ran_f[evalIdx]); |
||
3527 |
airMopError(mop); return 1; |
||
3528 |
} |
||
3529 |
} |
||
3530 |
/* single double vs vector double */ |
||
3531 |
✗✓ | 40800000 |
if (single_d != ran_d[evalIdx]) { |
3532 |
biffAddf(NRRD, "%s: %s (eval1_d(%.17g)=%.17g) != (evalN_d(%.17g)=%.17g)", |
||
3533 |
me, kstr, dom_d[evalIdx], single_d, |
||
3534 |
dom_d[evalIdx], ran_d[evalIdx]); |
||
3535 |
airMopError(mop); return 1; |
||
3536 |
} |
||
3537 |
/* single float vs single double */ |
||
3538 |
✗✓ | 40800000 |
if (fabs(single_f - single_d) > epsilon) { |
3539 |
diffOkEvalNum++; |
||
3540 |
if (diffOkEvalNum > diffOkEvalMax) { |
||
3541 |
biffAddf(NRRD, |
||
3542 |
"%s: %s |eval1_f(%.17g)=%.17g) - (eval1_d(%.17g)=%.17g)|" |
||
3543 |
" %.17g > epsilon %.17g too many times (%u > %u)", me, |
||
3544 |
kstr, dom_f[evalIdx], single_f, dom_d[evalIdx], single_d, |
||
3545 |
fabs(single_f - single_d), epsilon, |
||
3546 |
diffOkEvalNum, diffOkEvalMax); |
||
3547 |
airMopError(mop); return 1; |
||
3548 |
} |
||
3549 |
} |
||
3550 |
/* check whether we're the derivative of ikern */ |
||
3551 |
✓✓ | 40800000 |
if (ikern) { |
3552 |
double forw, back, ndrv; |
||
3553 |
12720000 |
forw = ikern->eval1_d(dom_d[evalIdx] + wee/2, iparm); |
|
3554 |
12720000 |
back = ikern->eval1_d(dom_d[evalIdx] - wee/2, iparm); |
|
3555 |
12720000 |
ndrv = (forw - back)/wee; |
|
3556 |
✓✓ | 12720000 |
if (fabs(ndrv - single_d) > epsilon) { |
3557 |
42 |
diffOkIntglNum++; |
|
3558 |
✗✓ | 42 |
if (diffOkIntglNum > diffOkIntglMax) { |
3559 |
biffAddf(NRRD, "%s: %s(%.17g) |num deriv(%s) %.17g - %.17g| " |
||
3560 |
"%.17g > %.17g too many times (%u > %u)", |
||
3561 |
me, kstr, dom_d[evalIdx], ikern->name, ndrv, single_d, |
||
3562 |
fabs(ndrv - single_d), epsilon, |
||
3563 |
diffOkIntglNum, diffOkIntglMax); |
||
3564 |
airMopError(mop); return 1; |
||
3565 |
} |
||
3566 |
} |
||
3567 |
12720000 |
} |
|
3568 |
40800000 |
} |
|
3569 |
340 |
integral *= 2*supp/(AIR_CAST(double, evalNum)); |
|
3570 |
/* the "cheap" kernel alone gets a pass on reporting its integral */ |
||
3571 |
✓✓ | 340 |
if (nrrdKernelCheap != kern) { |
3572 |
double hackeps=10; |
||
3573 |
/* hackeps is clearly a hack to permit the integral to have greater |
||
3574 |
error than any single evaluation; there must be a more principled |
||
3575 |
way to set this */ |
||
3576 |
✗✓ | 338 |
if (fabs(integral - kern->integral(parm)) > hackeps*epsilon) { |
3577 |
biffAddf(NRRD, "%s: %s |numerical integral %.17g - claimed %.17g| " |
||
3578 |
"%.17g > %.17g", me, kstr, integral, kern->integral(parm), |
||
3579 |
fabs(integral - kern->integral(parm)), hackeps*epsilon); |
||
3580 |
airMopError(mop); return 1; |
||
3581 |
} |
||
3582 |
338 |
} |
|
3583 |
|||
3584 |
/* HEY check being derivative of ikern/iparm */ |
||
3585 |
AIR_UNUSED(ikern); |
||
3586 |
AIR_UNUSED(iparm); |
||
3587 |
|||
3588 |
340 |
airMopOkay(mop); |
|
3589 |
340 |
return 0; |
|
3590 |
340 |
} |
|
3591 |
|||
3592 |
int |
||
3593 |
nrrdKernelParm0IsScale(const NrrdKernel *kern) { |
||
3594 |
int ret; |
||
3595 |
|||
3596 |
if (!kern) { |
||
3597 |
ret = 0; |
||
3598 |
} else if (nrrdKernelHann == kern || |
||
3599 |
nrrdKernelHannD == kern || |
||
3600 |
nrrdKernelHannDD == kern || |
||
3601 |
nrrdKernelBlackman == kern || |
||
3602 |
nrrdKernelBlackmanD == kern || |
||
3603 |
nrrdKernelBlackmanDD == kern || |
||
3604 |
nrrdKernelZero == kern || |
||
3605 |
nrrdKernelBox == kern || |
||
3606 |
nrrdKernelCheap == kern || |
||
3607 |
nrrdKernelTent == kern || |
||
3608 |
nrrdKernelForwDiff == kern || |
||
3609 |
nrrdKernelCentDiff == kern || |
||
3610 |
nrrdKernelBCCubic == kern || |
||
3611 |
nrrdKernelBCCubicD == kern || |
||
3612 |
nrrdKernelBCCubicDD == kern || |
||
3613 |
nrrdKernelAQuartic == kern || |
||
3614 |
nrrdKernelAQuarticD == kern || |
||
3615 |
nrrdKernelAQuarticDD == kern || |
||
3616 |
nrrdKernelGaussian == kern || |
||
3617 |
nrrdKernelGaussianD == kern || |
||
3618 |
nrrdKernelGaussianDD == kern || |
||
3619 |
nrrdKernelDiscreteGaussian == kern) { |
||
3620 |
ret = 1; |
||
3621 |
} else { |
||
3622 |
ret = 0; |
||
3623 |
} |
||
3624 |
return ret; |
||
3625 |
} |
Generated by: GCOVR (Version 3.3) |