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 |
|
|
|
25 |
|
|
#include "air.h" |
26 |
|
|
|
27 |
|
|
/* |
28 |
|
|
** by the way, the organization of functions into files is a little |
29 |
|
|
** arbitrary around here |
30 |
|
|
*/ |
31 |
|
|
|
32 |
|
|
/* |
33 |
|
|
** from: Gavin C Cawley, "On a Fast, Compact Approximation of the |
34 |
|
|
** Exponential Function" Neural Computation, 2000, 12(9), 2009-2012. |
35 |
|
|
** |
36 |
|
|
** which in turn is based on: N N Schraudolph, "A fast, compact approximation |
37 |
|
|
** of the exponential function." Neural Computation, 1999, 11(4), 853-862. |
38 |
|
|
** http://cnl.salk.edu/~schraudo/pubs/Schraudolph99.pdf |
39 |
|
|
** |
40 |
|
|
** some possible code which does not depend on endian |
41 |
|
|
** http://www.machinedlearnings.com/2011/06/fast-approximate-logarithm-exponential.html |
42 |
|
|
*/ |
43 |
|
|
|
44 |
|
|
typedef union { |
45 |
|
|
double dd; |
46 |
|
|
int nn[2]; |
47 |
|
|
} eco_t; |
48 |
|
|
|
49 |
|
|
#define EXPA (1048576/0.69314718055994530942) |
50 |
|
|
#define EXPC 60801 |
51 |
|
|
double |
52 |
|
|
airFastExp(double val) { |
53 |
|
|
eco_t eco; |
54 |
|
|
double ret; |
55 |
|
|
int tmpI, EXPI; |
56 |
|
|
|
57 |
|
|
/* HEY: COPY AND PASTE from airMyEndian */ |
58 |
|
|
tmpI = 1; |
59 |
|
|
EXPI = *(AIR_CAST(char*, &tmpI)); |
60 |
|
|
eco.nn[EXPI] = AIR_CAST(int, (EXPA*(val)) + (1072693248 - EXPC)); |
61 |
|
|
eco.nn[1-EXPI] = 0; |
62 |
|
|
ret = (eco.dd > 0.0 |
63 |
|
|
? eco.dd |
64 |
|
|
/* seems that only times this happens is when the real exp() |
65 |
|
|
returns either 0 or +inf */ |
66 |
|
|
: (val < 0 ? 0 : AIR_POS_INF)); |
67 |
|
|
return ret; |
68 |
|
|
} |
69 |
|
|
#undef EXPA |
70 |
|
|
#undef EXPC |
71 |
|
|
|
72 |
|
|
/* |
73 |
|
|
** based on MiniMaxApproximation, but this has failed in its goal |
74 |
|
|
** of being faster than libc's exp(), so should be considered |
75 |
|
|
** a work-in-progress |
76 |
|
|
*/ |
77 |
|
|
double |
78 |
|
|
airExp(double x) { |
79 |
|
|
double num, den, ee; |
80 |
|
|
unsigned int pp; |
81 |
|
|
|
82 |
|
|
if (AIR_IN_CL(-1, x, 1)) { |
83 |
|
|
num = 1 + x*(0.500241 + x*(0.107193 + (0.0118938 + 0.000591457*x)*x)); |
84 |
|
|
den = 1 + x*(-0.499759 + x*(0.106952 + (-0.0118456 + 0.000587495*x)*x)); |
85 |
|
|
ee = num/den; |
86 |
|
|
} else if (x > 1) { |
87 |
|
|
pp = 0; |
88 |
|
|
while (x > 2) { |
89 |
|
|
x /= 2; |
90 |
|
|
pp += 1; |
91 |
|
|
} |
92 |
|
|
num = 1 + x*(0.552853 + x*(0.135772 + (0.0183685 + 0.00130944*x)*x)); |
93 |
|
|
den = 1 + x*(-0.44714 + x*(0.0828937 + (-0.00759541 + 0.000291662*x)*x)); |
94 |
|
|
ee = num/den; |
95 |
|
|
while (pp) { |
96 |
|
|
ee *= ee; |
97 |
|
|
pp -= 1; |
98 |
|
|
} |
99 |
|
|
} else if (x < -1) { |
100 |
|
|
pp = 0; |
101 |
|
|
while (x < -2) { |
102 |
|
|
x /= 2; |
103 |
|
|
pp += 1; |
104 |
|
|
} |
105 |
|
|
num = 0.999999+x*(0.44726+x*(0.0829439 + (0.00760326 + 0.000292122*x)*x)); |
106 |
|
|
den = 1 + x*(-0.552732 + x*(0.135702 + (-0.0183511 + 0.00130689*x)*x)); |
107 |
|
|
ee = num/den; |
108 |
|
|
while (pp) { |
109 |
|
|
ee *= ee; |
110 |
|
|
pp -= 1; |
111 |
|
|
} |
112 |
|
|
} else { |
113 |
|
|
/* x is probably not finite */ |
114 |
|
|
ee = exp(x); |
115 |
|
|
} |
116 |
|
|
return ee; |
117 |
|
|
} |
118 |
|
|
|
119 |
|
|
/* |
120 |
|
|
******** airNormalRand |
121 |
|
|
** |
122 |
|
|
** generates two numbers with normal distribution (mean 0, stdv 1) |
123 |
|
|
** using the Box-Muller transform. |
124 |
|
|
** |
125 |
|
|
** on (seemingly sound) advice of |
126 |
|
|
** <http://www.taygeta.com/random/gaussian.html>, |
127 |
|
|
** I'm using the polar form of the Box-Muller transform, instead of the |
128 |
|
|
** Cartesian one described at |
129 |
|
|
** <http://mathworld.wolfram.com/Box-MullerTransformation.html> |
130 |
|
|
** |
131 |
|
|
** this is careful to not write into given NULL pointers |
132 |
|
|
*/ |
133 |
|
|
void |
134 |
|
|
airNormalRand(double *z1, double *z2) { |
135 |
|
|
double w, x1, x2; |
136 |
|
|
|
137 |
|
11084580 |
do { |
138 |
|
7057819 |
x1 = 2*airDrandMT() - 1; |
139 |
|
7057819 |
x2 = 2*airDrandMT() - 1; |
140 |
|
7057819 |
w = x1*x1 + x2*x2; |
141 |
✓✓ |
7057819 |
} while ( w >= 1 ); |
142 |
|
5542290 |
w = sqrt((-2*log(w))/w); |
143 |
✓✓ |
5542290 |
if (z1) { |
144 |
|
5532290 |
*z1 = x1*w; |
145 |
|
5532290 |
} |
146 |
✓✓ |
5542290 |
if (z2) { |
147 |
|
84050 |
*z2 = x2*w; |
148 |
|
84050 |
} |
149 |
|
|
return; |
150 |
|
5542290 |
} |
151 |
|
|
|
152 |
|
|
void |
153 |
|
|
airNormalRand_r(double *z1, double *z2, airRandMTState *state) { |
154 |
|
|
double w, x1, x2; |
155 |
|
|
|
156 |
|
10532 |
do { |
157 |
|
6713 |
x1 = 2*airDrandMT_r(state) - 1; |
158 |
|
6713 |
x2 = 2*airDrandMT_r(state) - 1; |
159 |
|
6713 |
w = x1*x1 + x2*x2; |
160 |
✓✓ |
6713 |
} while ( w >= 1 ); |
161 |
|
5266 |
w = sqrt((-2*log(w))/w); |
162 |
✓✗ |
5266 |
if (z1) { |
163 |
|
5266 |
*z1 = x1*w; |
164 |
|
5266 |
} |
165 |
✓✓ |
5266 |
if (z2) { |
166 |
|
3389 |
*z2 = x2*w; |
167 |
|
3389 |
} |
168 |
|
|
return; |
169 |
|
5266 |
} |
170 |
|
|
|
171 |
|
|
/* |
172 |
|
|
******** airShuffle() |
173 |
|
|
** |
174 |
|
|
** generates a random permutation of integers [0..N-1] if perm is non-zero, |
175 |
|
|
** otherwise, just fills buff with [0..N-1] in order |
176 |
|
|
** |
177 |
|
|
** see http://en.wikipedia.org/wiki/Knuth_shuffle |
178 |
|
|
*/ |
179 |
|
|
void |
180 |
|
|
airShuffle(unsigned int *buff, unsigned int N, int perm) { |
181 |
|
|
unsigned int i; |
182 |
|
|
|
183 |
|
|
if (!(buff && N > 0)) { |
184 |
|
|
return; |
185 |
|
|
} |
186 |
|
|
|
187 |
|
|
for (i=0; i<N; i++) { |
188 |
|
|
buff[i] = i; |
189 |
|
|
} |
190 |
|
|
if (perm) { |
191 |
|
|
unsigned int swp, tmp; |
192 |
|
|
while (N > 1) { |
193 |
|
|
swp = airRandInt(N); |
194 |
|
|
N--; |
195 |
|
|
tmp = buff[N]; |
196 |
|
|
buff[N] = buff[swp]; |
197 |
|
|
buff[swp] = tmp; |
198 |
|
|
} |
199 |
|
|
} |
200 |
|
|
} |
201 |
|
|
|
202 |
|
|
void |
203 |
|
|
airShuffle_r(airRandMTState *state, |
204 |
|
|
unsigned int *buff, unsigned int N, int perm) { |
205 |
|
|
unsigned int i; |
206 |
|
|
|
207 |
|
|
/* HEY !!! COPY AND PASTE !!!! */ |
208 |
|
|
if (!(buff && N > 0)) { |
209 |
|
|
return; |
210 |
|
|
} |
211 |
|
|
|
212 |
|
|
for (i=0; i<N; i++) { |
213 |
|
|
buff[i] = i; |
214 |
|
|
} |
215 |
|
|
if (perm) { |
216 |
|
|
unsigned int swp, tmp; |
217 |
|
|
while (N > 1) { |
218 |
|
|
swp = airRandInt_r(state, N); |
219 |
|
|
N--; |
220 |
|
|
tmp = buff[N]; |
221 |
|
|
buff[N] = buff[swp]; |
222 |
|
|
buff[swp] = tmp; |
223 |
|
|
} |
224 |
|
|
} |
225 |
|
|
/* HEY !!! COPY AND PASTE !!!! */ |
226 |
|
|
} |
227 |
|
|
|
228 |
|
|
double |
229 |
|
|
airSgnPow(double v, double p) { |
230 |
|
|
|
231 |
|
|
return (p == 1 |
232 |
|
|
? v |
233 |
|
|
: (v >= 0 |
234 |
|
|
? pow(v, p) |
235 |
|
|
: -pow(-v, p))); |
236 |
|
|
} |
237 |
|
|
|
238 |
|
|
double |
239 |
|
|
airFlippedSgnPow(double vv, double pp) { |
240 |
|
|
double sn=1.0; |
241 |
|
|
|
242 |
|
|
if (1.0 == pp) { |
243 |
|
|
return vv; |
244 |
|
|
} |
245 |
|
|
if (vv < 0) { |
246 |
|
|
sn = -1.0; |
247 |
|
|
vv = -vv; |
248 |
|
|
} |
249 |
|
|
return sn*(1.0 - pow(1.0 - AIR_MIN(1.0, vv), pp)); |
250 |
|
|
} |
251 |
|
|
|
252 |
|
|
double |
253 |
|
|
airIntPow(double v, int p) { |
254 |
|
|
double sq, ret; |
255 |
|
|
|
256 |
✓✗ |
2064960 |
if (p > 0) { |
257 |
|
|
sq = v; |
258 |
✓✓ |
3438720 |
while (!(p & 1)) { |
259 |
|
|
/* while the low bit is zero */ |
260 |
|
686880 |
p >>= 1; |
261 |
|
686880 |
sq *= sq; |
262 |
|
|
} |
263 |
|
|
/* must terminate because we know p != 0, and when |
264 |
|
|
it terminates we know that the low bit is 1 */ |
265 |
|
|
ret = sq; |
266 |
✗✓ |
2064960 |
while (p >>= 1) { |
267 |
|
|
/* while there are any non-zero bits in p left */ |
268 |
|
|
sq *= sq; |
269 |
|
|
if (p & 1) { |
270 |
|
|
ret *= sq; |
271 |
|
|
} |
272 |
|
|
} |
273 |
|
|
} else if (p < 0) { |
274 |
|
|
ret = airIntPow(1.0/v, -p); |
275 |
|
|
} else { |
276 |
|
|
ret = 1.0; |
277 |
|
|
} |
278 |
|
|
|
279 |
|
1032480 |
return ret; |
280 |
|
|
} |
281 |
|
|
|
282 |
|
|
/* |
283 |
|
|
******** airLog2() |
284 |
|
|
** |
285 |
|
|
** silly little function which returns log_2(n) if n is exactly a power of 2, |
286 |
|
|
** and -1 otherwise |
287 |
|
|
*/ |
288 |
|
|
int |
289 |
|
|
airLog2(size_t _nn) { |
290 |
|
|
size_t nn; |
291 |
|
|
int ret; |
292 |
|
|
|
293 |
|
|
nn = _nn; |
294 |
✗✓ |
122 |
if (0 == nn) { |
295 |
|
|
/* 0 is not a power of 2 */ |
296 |
|
|
ret = -1; |
297 |
|
|
} else { |
298 |
|
|
int alog = 0; |
299 |
|
|
/* divide by 2 while its non-zero and the low bit is off */ |
300 |
✓✗✓✓
|
1578 |
while (!!nn && !(nn & 1)) { |
301 |
|
465 |
alog += 1; |
302 |
|
465 |
nn /= 2; |
303 |
|
|
} |
304 |
✓✓ |
61 |
if (1 == nn) { |
305 |
|
|
ret = alog; |
306 |
|
31 |
} else { |
307 |
|
|
ret = -1; |
308 |
|
|
} |
309 |
|
|
} |
310 |
|
61 |
return ret; |
311 |
|
|
} |
312 |
|
|
|
313 |
|
|
int |
314 |
|
|
airSgn(double v) { |
315 |
✓✓ |
630 |
return (v > 0 |
316 |
|
|
? 1 |
317 |
|
90 |
: (v < 0 |
318 |
|
|
? -1 |
319 |
|
|
: 0)); |
320 |
|
|
} |
321 |
|
|
|
322 |
|
|
/* |
323 |
|
|
******** airCbrt |
324 |
|
|
** |
325 |
|
|
** cbrt() isn't in C89, so any hacks to create a stand-in for cbrt() |
326 |
|
|
** are done here. |
327 |
|
|
*/ |
328 |
|
|
double |
329 |
|
|
airCbrt(double v) { |
330 |
|
|
#if defined(_WIN32) || defined(__STRICT_ANSI__) |
331 |
|
|
return (v < 0.0 ? -pow(-v,1.0/3.0) : pow(v,1.0/3.0)); |
332 |
|
|
#else |
333 |
|
8000 |
return cbrt(v); |
334 |
|
|
#endif |
335 |
|
|
} |
336 |
|
|
|
337 |
|
|
/* |
338 |
|
|
** skewness of three numbers, scaled to fit in [-1,+1] |
339 |
|
|
** -1: small, big, big |
340 |
|
|
** +1: small, small, big |
341 |
|
|
*/ |
342 |
|
|
double |
343 |
|
|
airMode3_d(const double _v[3]) { |
344 |
|
|
double num, den, mean, v[3]; |
345 |
|
|
|
346 |
|
|
mean = (_v[0] + _v[1] + _v[2])/3; |
347 |
|
|
v[0] = _v[0] - mean; |
348 |
|
|
v[1] = _v[1] - mean; |
349 |
|
|
v[2] = _v[2] - mean; |
350 |
|
|
num = (v[0] + v[1] - 2*v[2])*(2*v[0] - v[1] - v[2])*(v[0] - 2*v[1] + v[2]); |
351 |
|
|
den = v[0]*v[0] + v[1]*v[1] + v[2]*v[2] - v[1]*v[2] - v[0]*v[1] - v[0]*v[2]; |
352 |
|
|
den = sqrt(den); |
353 |
|
|
return (den ? num/(2*den*den*den) : 0); |
354 |
|
|
} |
355 |
|
|
|
356 |
|
|
double |
357 |
|
|
airMode3(double v0, double v1, double v2) { |
358 |
|
|
double v[3]; |
359 |
|
|
|
360 |
|
|
v[0] = v0; |
361 |
|
|
v[1] = v1; |
362 |
|
|
v[2] = v2; |
363 |
|
|
return airMode3_d(v); |
364 |
|
|
} |
365 |
|
|
|
366 |
|
|
double |
367 |
|
|
airGaussian(double x, double mean, double stdv) { |
368 |
|
|
|
369 |
|
|
x = x - mean; |
370 |
|
|
return exp(-(x*x)/(2*stdv*stdv))/(stdv*sqrt(2*AIR_PI)); |
371 |
|
|
} |
372 |
|
|
|
373 |
|
|
/* |
374 |
|
|
** The function approximations below were done by GLK in Mathematica, |
375 |
|
|
** using its MiniMaxApproximation[] function. The functional forms |
376 |
|
|
** used for the Bessel functions were copied from Numerical Recipes |
377 |
|
|
** (which were in turn copied from the "Handbook of Mathematical |
378 |
|
|
** Functions with Formulas, Graphs, and Mathematical Tables" by |
379 |
|
|
** Abramowitz and Stegun), but the coefficients here represent |
380 |
|
|
** an increase in accuracy. |
381 |
|
|
** |
382 |
|
|
** The rational functions (crudely copy/paste from Mathematica into |
383 |
|
|
** this file) upon which the approximations are based have a relative |
384 |
|
|
** error of less than 10^-9, at least on the intervals on which they |
385 |
|
|
** were created (in the case of the second branch of the |
386 |
|
|
** approximation, the lower end of the interval was chosen as close to |
387 |
|
|
** zero as possible). The relative error of the total approximation |
388 |
|
|
** may be greater. |
389 |
|
|
*/ |
390 |
|
|
|
391 |
|
|
double |
392 |
|
|
airErfc(double x) { |
393 |
|
|
double ax, y, b; |
394 |
|
|
|
395 |
|
1560110 |
ax = AIR_ABS(x); |
396 |
✓✓ |
780055 |
if (ax < 0.9820789566638689) { |
397 |
|
94640 |
b = (0.9999999999995380997 + ax*(-1.0198241793287349401 + |
398 |
|
94640 |
ax*(0.37030717279808919457 + ax*(-0.15987839763633308864 + |
399 |
|
189280 |
ax*(0.12416682580357861661 + (-0.04829622197742573233 + |
400 |
|
283920 |
0.0066094852952188890901*ax)*ax)))))/ |
401 |
|
94640 |
(1 + ax*(0.1085549876246959456 + ax*(0.49279836663925410323 + |
402 |
|
94640 |
ax*(0.020058474597886988472 + ax*(0.10597158000597863862 + |
403 |
|
94640 |
(-0.0012466514192679810876 + 0.0099475501252703646772*ax)*ax))))); |
404 |
✓✓ |
780055 |
} else if (ax < 2.020104167011169) { |
405 |
|
101331 |
y = ax - 1; |
406 |
|
101331 |
b = (0.15729920705029613528 + y*(-0.37677358667097191131 + |
407 |
|
101331 |
y*(0.3881956571123873123 + y*(-0.22055886537359936478 + |
408 |
|
202662 |
y*(0.073002666454740425451 + (-0.013369369366972563804 + |
409 |
|
303993 |
0.0010602024397541548717*y)*y)))))/ |
410 |
|
101331 |
(1 + y*(0.243700597525225235 + y*(0.47203101881562848941 + |
411 |
|
101331 |
y*(0.080051054975943863026 + y*(0.083879049958465759886 + |
412 |
|
101331 |
(0.0076905426306038205308 + 0.0058528196473365970129*y)*y))))); |
413 |
|
101331 |
} else { |
414 |
|
584084 |
y = 2/ax; |
415 |
|
584084 |
b = (-2.7460876468061399519e-14 + y*(0.28209479188874503125 + |
416 |
|
584084 |
y*(0.54260398586720212019 + y*(0.68145162781305697748 + |
417 |
|
1168168 |
(0.44324741856237800393 + 0.13869182273440856508*y)*y))))/ |
418 |
|
584084 |
(1 + y*(1.9234811027995435174 + y*(2.5406810534399069812 + |
419 |
|
1168168 |
y*(1.8117409273494093139 + (0.76205066033991530997 + |
420 |
|
1168168 |
0.13794679143736608167*y)*y)))); |
421 |
|
584084 |
b *= exp(-x*x); |
422 |
|
|
} |
423 |
✓✓ |
780055 |
if (x < 0) { |
424 |
|
322496 |
b = 2-b; |
425 |
|
322496 |
} |
426 |
|
780055 |
return b; |
427 |
|
|
} |
428 |
|
|
|
429 |
|
|
double |
430 |
|
|
airErf(double x) { |
431 |
|
1560110 |
return 1.0 - airErfc(x); |
432 |
|
|
} |
433 |
|
|
|
434 |
|
|
/* |
435 |
|
|
******** airBesselI0 |
436 |
|
|
** |
437 |
|
|
** modified Bessel function of the first kind, order 0 |
438 |
|
|
*/ |
439 |
|
|
double |
440 |
|
|
airBesselI0(double x) { |
441 |
|
|
double b, ax, y; |
442 |
|
|
|
443 |
|
|
ax = AIR_ABS(x); |
444 |
|
|
if (ax < 5.664804810929075) { |
445 |
|
|
y = x/5.7; |
446 |
|
|
y *= y; |
447 |
|
|
b = (0.9999999996966272 + y*(7.7095783675529646 + |
448 |
|
|
y*(13.211021909077445 + y*(8.648398832703904 + |
449 |
|
|
(2.5427099920536578 + 0.3103650754941674*y)*y))))/ |
450 |
|
|
(1 + y*(-0.41292170755003793 + (0.07122966874756179 |
451 |
|
|
- 0.005182728492608365*y)*y)); |
452 |
|
|
} else { |
453 |
|
|
y = 5.7/ax; |
454 |
|
|
b = (0.398942280546057 + y*(-0.749709626164583 + |
455 |
|
|
y*(0.507462772839054 + y*(-0.0918770649691261 + |
456 |
|
|
(-0.00135238228377743 - 0.0000897561853670307*y)*y))))/ |
457 |
|
|
(1 + y*(-1.90117313211089 + (1.31154807540649 |
458 |
|
|
- 0.255339661975509*y)*y)); |
459 |
|
|
b *= (exp(ax)/sqrt(ax)); |
460 |
|
|
} |
461 |
|
|
return b; |
462 |
|
|
} |
463 |
|
|
|
464 |
|
|
/* |
465 |
|
|
******** airBesselI0ExpScaled |
466 |
|
|
** |
467 |
|
|
** modified Bessel function of the first kind, order 0, |
468 |
|
|
** scaled by exp(-abs(x)). |
469 |
|
|
*/ |
470 |
|
|
double |
471 |
|
|
airBesselI0ExpScaled(double x) { |
472 |
|
|
double b, ax, y; |
473 |
|
|
|
474 |
|
4318780 |
ax = AIR_ABS(x); |
475 |
✓✗ |
2159390 |
if (ax < 5.664804810929075) { |
476 |
|
2159390 |
y = x/5.7; |
477 |
|
2159390 |
y *= y; |
478 |
|
2159390 |
b = (0.9999999996966272 + y*(7.7095783675529646 + |
479 |
|
2159390 |
y*(13.211021909077445 + y*(8.648398832703904 + |
480 |
|
4318780 |
(2.5427099920536578 + 0.3103650754941674*y)*y))))/ |
481 |
|
2159390 |
(1 + y*(-0.41292170755003793 + (0.07122966874756179 |
482 |
|
2159390 |
- 0.005182728492608365*y)*y)); |
483 |
|
2159390 |
b *= exp(-ax); |
484 |
|
2159390 |
} else { |
485 |
|
|
y = 5.7/ax; |
486 |
|
|
b = (0.398942280546057 + y*(-0.749709626164583 + |
487 |
|
|
y*(0.507462772839054 + y*(-0.0918770649691261 + |
488 |
|
|
(-0.00135238228377743 - 0.0000897561853670307*y)*y))))/ |
489 |
|
|
(1 + y*(-1.90117313211089 + (1.31154807540649 |
490 |
|
|
- 0.255339661975509*y)*y)); |
491 |
|
|
b *= (1/sqrt(ax)); |
492 |
|
|
} |
493 |
|
2159390 |
return b; |
494 |
|
|
} |
495 |
|
|
|
496 |
|
|
|
497 |
|
|
/* |
498 |
|
|
******** airBesselI1 |
499 |
|
|
** |
500 |
|
|
** modified Bessel function of the first kind, order 1 |
501 |
|
|
*/ |
502 |
|
|
double |
503 |
|
|
airBesselI1(double x) { |
504 |
|
|
double b, ax, y; |
505 |
|
|
|
506 |
|
|
ax = AIR_ABS(x); |
507 |
|
|
if (ax < 6.449305566387246) { |
508 |
|
|
y = x/6.45; |
509 |
|
|
y *= y; |
510 |
|
|
b = ax*(0.4999999998235554 + y*(2.370331499358438 + |
511 |
|
|
y*(3.3554331305863787 + y*(2.0569974969268707 + |
512 |
|
|
(0.6092719473097832 + 0.0792323006694466*y)*y))))/ |
513 |
|
|
(1 + y*(-0.4596495788370524 + (0.08677361454866868 \ |
514 |
|
|
- 0.006777712190188699*y)*y)); |
515 |
|
|
} else { |
516 |
|
|
y = 6.45/ax; |
517 |
|
|
b = (0.398942280267484 + y*(-0.669339325353065 + |
518 |
|
|
y*(0.40311772245257 + y*(-0.0766281832045885 + |
519 |
|
|
(0.00248933264397244 + 0.0000703849046144657*y)*y))))/ |
520 |
|
|
(1 + y*(-1.61964537617937 + (0.919118239717915 - |
521 |
|
|
0.142824922601647*y)*y)); |
522 |
|
|
b *= exp(ax)/sqrt(ax); |
523 |
|
|
} |
524 |
|
|
return x < 0.0 ? -b : b; |
525 |
|
|
} |
526 |
|
|
|
527 |
|
|
/* |
528 |
|
|
******** airBesselI1ExpScaled |
529 |
|
|
** |
530 |
|
|
** modified Bessel function of the first kind, order 1, |
531 |
|
|
** scaled by exp(-abs(x)) |
532 |
|
|
*/ |
533 |
|
|
double |
534 |
|
|
airBesselI1ExpScaled(double x) { |
535 |
|
|
double b, ax, y; |
536 |
|
|
|
537 |
|
1441352 |
ax = AIR_ABS(x); |
538 |
✓✗ |
720676 |
if (ax < 6.449305566387246) { |
539 |
|
720676 |
y = x/6.45; |
540 |
|
720676 |
y *= y; |
541 |
|
720676 |
b = ax*(0.4999999998235554 + y*(2.370331499358438 + |
542 |
|
720676 |
y*(3.3554331305863787 + y*(2.0569974969268707 + |
543 |
|
1441352 |
(0.6092719473097832 + 0.0792323006694466*y)*y))))/ |
544 |
|
720676 |
(1 + y*(-0.4596495788370524 + (0.08677361454866868 \ |
545 |
|
720676 |
- 0.006777712190188699*y)*y)); |
546 |
|
720676 |
b *= exp(-ax); |
547 |
|
720676 |
} else { |
548 |
|
|
y = 6.45/ax; |
549 |
|
|
b = (0.398942280267484 + y*(-0.669339325353065 + |
550 |
|
|
y*(0.40311772245257 + y*(-0.0766281832045885 + |
551 |
|
|
(0.00248933264397244 + 0.0000703849046144657*y)*y))))/ |
552 |
|
|
(1 + y*(-1.61964537617937 + (0.919118239717915 - |
553 |
|
|
0.142824922601647*y)*y)); |
554 |
|
|
b *= 1/sqrt(ax); |
555 |
|
|
} |
556 |
|
720676 |
return x < 0.0 ? -b : b; |
557 |
|
|
} |
558 |
|
|
|
559 |
|
|
/* |
560 |
|
|
******** airLogBesselI0 |
561 |
|
|
** |
562 |
|
|
** natural logarithm of airBesselI0 |
563 |
|
|
*/ |
564 |
|
|
double |
565 |
|
|
airLogBesselI0(double x) { |
566 |
|
|
double b, ax, y; |
567 |
|
|
|
568 |
|
|
ax = AIR_ABS(x); |
569 |
|
|
if (ax < 4.985769687853781) { |
570 |
|
|
y = x/5.0; |
571 |
|
|
y *= y; |
572 |
|
|
b = (5.86105592521167098e-27 + y*(6.2499999970669017 + |
573 |
|
|
y*(41.1327842713925212 + y*(80.9030404787605539 + |
574 |
|
|
y*(50.7576267390706893 + 6.88231907401413133*y)))))/ |
575 |
|
|
(1 + y*(8.14374525361325784 + y*(21.3288286560361152 + |
576 |
|
|
y*(20.0880670952325953 + (5.5138982784800139 + |
577 |
|
|
0.186784275148079847*y)*y)))); |
578 |
|
|
} else { |
579 |
|
|
y = 5.0/ax; |
580 |
|
|
b = (-0.91893853280169872884 + y*(2.7513907055333657679 + |
581 |
|
|
y*(-3.369024122613176551 + y*(1.9164545708124343838 + |
582 |
|
|
(-0.46136261965797010108 + 0.029092365715948197066*y)*y))))/ |
583 |
|
|
(1 + y*(-2.9668913151685312745 + y*(3.5882191453626541066 + |
584 |
|
|
y*(-1.9954040017063882247 + (0.45606687718126481603 - |
585 |
|
|
0.0231678041994100784*y)*y)))); |
586 |
|
|
b += ax - log(ax)/2; |
587 |
|
|
} |
588 |
|
|
return b; |
589 |
|
|
} |
590 |
|
|
|
591 |
|
|
/* |
592 |
|
|
******** airLogRician |
593 |
|
|
** |
594 |
|
|
** natural logarithm of Rician distribution |
595 |
|
|
** mes is measured value |
596 |
|
|
** tru is "true" underlying value |
597 |
|
|
** sig is sigma of 2-D Gaussian |
598 |
|
|
*/ |
599 |
|
|
double |
600 |
|
|
airLogRician(double mes, double tru, double sig) { |
601 |
|
|
double lb, ss; |
602 |
|
|
|
603 |
|
|
ss = sig*sig; |
604 |
|
|
lb = airLogBesselI0(mes*tru/ss); |
605 |
|
|
return lb + log(mes/ss) - (mes*mes + tru*tru)/(2*ss); |
606 |
|
|
} |
607 |
|
|
|
608 |
|
|
double |
609 |
|
|
airRician(double mes, double tru, double sig) { |
610 |
|
|
return exp(airLogRician(mes, tru, sig)); |
611 |
|
|
} |
612 |
|
|
|
613 |
|
|
/* |
614 |
|
|
******** airBesselI1By0 |
615 |
|
|
** |
616 |
|
|
** the quotient airBesselI1(x)/airBesselI0(x) |
617 |
|
|
*/ |
618 |
|
|
double |
619 |
|
|
airBesselI1By0(double x) { |
620 |
|
|
double q, ax, y; |
621 |
|
|
|
622 |
|
|
ax = AIR_ABS(x); |
623 |
|
|
if (ax < 2.2000207427754046) { |
624 |
|
|
y = ax/2.2; |
625 |
|
|
q = (1.109010375603908e-29 + y*(1.0999999994454934 + |
626 |
|
|
y*(0.05256560007682146 + y*(0.3835178789165919 + |
627 |
|
|
(0.011328636410807382 + 0.009066934622942833*y)*y))))/ |
628 |
|
|
(1 + y*(0.047786822784523904 + y*(0.9536550439261017 + |
629 |
|
|
(0.03918380275938573 + 0.09730715527121027*y)*y))); |
630 |
|
|
} else if (ax < 5.888258985638512) { |
631 |
|
|
y = (ax-2.2)/3.68; |
632 |
|
|
q = (0.7280299135046744 + y*(2.5697382341657002 + |
633 |
|
|
y*(3.69819451510548 + y*(3.131374238190916 + |
634 |
|
|
(1.2811958061688737 + 0.003601218043466571*y)*y))))/ |
635 |
|
|
(1 + y*(2.8268553393021527 + y*(4.164742157157812 + |
636 |
|
|
y*(3.2377768820326756 + 1.3051900460060342*y)))); |
637 |
|
|
} else { |
638 |
|
|
y = 5.88/ax; |
639 |
|
|
q = (1.000000000646262020372530870790956088593 + |
640 |
|
|
y*(-2.012513842496824157039372120680781513697 + |
641 |
|
|
y*(1.511644590219033259220408231325838531123 + |
642 |
|
|
(-0.3966391319921114140077576390415605232003 + |
643 |
|
|
0.02651815520696779849352690755529178056941*y)*y)))/ |
644 |
|
|
(1 + y*(-1.927479858946526082413004924812844224781 + |
645 |
|
|
y*(1.351359456116228102988125069310621733956 + |
646 |
|
|
(-0.288087717540546638165144937495654019162 + |
647 |
|
|
0.005906535730887518966127383058238522133819*y)*y))); |
648 |
|
|
} |
649 |
|
|
return x < 0.0 ? -q : q; |
650 |
|
|
} |
651 |
|
|
|
652 |
|
|
/* |
653 |
|
|
******** airBesselIn |
654 |
|
|
** |
655 |
|
|
** modified Bessel function of the first kind, order n. |
656 |
|
|
** |
657 |
|
|
*/ |
658 |
|
|
double |
659 |
|
|
airBesselIn(int nn, double xx) { |
660 |
|
|
double tax, bb, bi, bim, bip; |
661 |
|
|
int ii, an, top; |
662 |
|
|
|
663 |
|
|
an = AIR_ABS(nn); |
664 |
|
|
if (0 == an) { |
665 |
|
|
return airBesselI0(xx); |
666 |
|
|
} else if (1 == an) { |
667 |
|
|
return airBesselI1(xx); |
668 |
|
|
} |
669 |
|
|
|
670 |
|
|
if (0.0 == xx) { |
671 |
|
|
return 0.0; |
672 |
|
|
} |
673 |
|
|
|
674 |
|
|
tax = 2.0/AIR_ABS(xx); |
675 |
|
|
bip = bb = 0.0; |
676 |
|
|
bi = 1.0; |
677 |
|
|
top = 2*(an + AIR_CAST(int, sqrt(40.0*an))); |
678 |
|
|
for (ii=top; ii > 0; ii--) { |
679 |
|
|
bim = bip + ii*tax*bi; |
680 |
|
|
bip = bi; |
681 |
|
|
bi = bim; |
682 |
|
|
if (AIR_ABS(bi) > 1.0e10) { |
683 |
|
|
bb *= 1.0e-10; |
684 |
|
|
bi *= 1.0e-10; |
685 |
|
|
bip*= 1.0e-10; |
686 |
|
|
} |
687 |
|
|
if (ii == an) { |
688 |
|
|
bb = bip; |
689 |
|
|
} |
690 |
|
|
} |
691 |
|
|
bb *= airBesselI0(xx)/bi; |
692 |
|
|
return (xx < 0.0 ? -bb : bb); |
693 |
|
|
} |
694 |
|
|
|
695 |
|
|
/* |
696 |
|
|
******** airBesselInExpScaled |
697 |
|
|
** |
698 |
|
|
** modified Bessel function of the first kind, order n, |
699 |
|
|
** scaled by exp(-abs(x)) |
700 |
|
|
** |
701 |
|
|
*/ |
702 |
|
|
double |
703 |
|
|
airBesselInExpScaled(int nn, double xx) { |
704 |
|
|
double tax, bb, bi, bim, bip, eps; |
705 |
|
|
int top, ii, an; |
706 |
|
|
|
707 |
|
5760132 |
an = AIR_ABS(nn); |
708 |
✓✓ |
2880066 |
if (0 == an) { |
709 |
|
360334 |
return airBesselI0ExpScaled(xx); |
710 |
✓✓ |
2519732 |
} else if (1 == an) { |
711 |
|
720676 |
return airBesselI1ExpScaled(xx); |
712 |
|
|
} |
713 |
|
|
|
714 |
✗✓ |
1799056 |
if (0 == xx) { |
715 |
|
|
return 0.0; |
716 |
|
|
} |
717 |
|
|
|
718 |
|
1799056 |
tax = 2.0/AIR_ABS(xx); |
719 |
|
|
bip = bb = 0.0; |
720 |
|
|
bi = 1.0; |
721 |
|
|
/* HEY: GLK tried to increase sqrt(40.0*an) to sqrt(100.0*an) to avoid |
722 |
|
|
jagged discontinuities in (e.g.) airBesselInExpScaled(n, 17*17); the |
723 |
|
|
problem was detected because of glitches in the highest blurring |
724 |
|
|
levels for scale-space feature detection; but that didn't quite |
725 |
|
|
work either; this will have to be debugged further! */ |
726 |
|
1799056 |
top = 2*(an + AIR_CAST(int, sqrt(40.0*an))); |
727 |
|
|
eps = 1.0e-10; |
728 |
✓✓ |
113254144 |
for (ii=top; ii > 0; ii--) { |
729 |
|
54828016 |
bim = bip + ii*tax*bi; |
730 |
|
|
bip = bi; |
731 |
|
|
bi = bim; |
732 |
✓✓ |
54828016 |
if (AIR_ABS(bi) > 1.0/eps) { |
733 |
|
6297098 |
bb *= eps; |
734 |
|
6297098 |
bi *= eps; |
735 |
|
6297098 |
bip*= eps; |
736 |
|
6297098 |
} |
737 |
✓✓ |
54828016 |
if (ii == an) { |
738 |
|
|
bb = bip; |
739 |
|
1799056 |
} |
740 |
|
|
} |
741 |
|
1799056 |
bb *= airBesselI0ExpScaled(xx)/bi; |
742 |
|
1799056 |
return (xx < 0.0 ? -bb : bb); |
743 |
|
2880066 |
} |
744 |
|
|
|
745 |
|
|
/* |
746 |
|
|
** based on: T. Lindeberg. "Effective Scale: A Natural Unit For |
747 |
|
|
** Measuring Scale-Space Lifetime" IEEE PAMI, 15:1068-1074 (1993) |
748 |
|
|
** |
749 |
|
|
** which includes tau(tee) as equation (29), |
750 |
|
|
** here taking A'' == 0 and B'' == 1, with |
751 |
|
|
** a0 and a1 as defined by eqs (22) and (23) |
752 |
|
|
** |
753 |
|
|
** Used MiniMaxApproximation[] from Mathematica (see |
754 |
|
|
** ~gk/papers/ssp/nb/effective-scale-TauOfTee.nb) to get functions, |
755 |
|
|
** but the specific functions and their domains could certainly be |
756 |
|
|
** improved upon. Also, the absence of conversions directly between |
757 |
|
|
** tau and sigma is quite unfortunate: going through tee loses |
758 |
|
|
** precision and takes more time. |
759 |
|
|
** |
760 |
|
|
** ACCURATE: can set this to 0 or 1: |
761 |
|
|
** 0: use a quick-and-dirty approximation to tau(tee), which |
762 |
|
|
** uses a straight line segment for small scales, and then |
763 |
|
|
** has a C^1-continuous transition to the large-scale approximation eq (33) |
764 |
|
|
** 1: careful approximation based on the MiniMaxApproximation[]s |
765 |
|
|
*/ |
766 |
|
|
#define ACCURATE 1 |
767 |
|
|
double |
768 |
|
|
airTauOfTime(double tee) { |
769 |
|
|
double tau; |
770 |
|
|
|
771 |
✗✓ |
12 |
if (tee < 0) { |
772 |
|
|
tau = 0; |
773 |
|
|
#if ACCURATE |
774 |
✓✓ |
6 |
} else if (tee < 1.49807) { |
775 |
|
|
/* mmtau0tweaked */ |
776 |
|
6 |
tau = (tee*(0.2756644487429131 + tee*(0.10594329088466668 + tee*(0.05514331911165778 + (0.021449249669475232 + 0.004417835440932558*tee)*tee))))/ |
777 |
|
3 |
(1.0 + tee*(-0.08684532328108877 + tee*(0.1792830876099199 + tee*(0.07468999631784223 + (0.012123550696192354 + 0.0021535864222409365*tee)*tee)))); |
778 |
✗✓ |
6 |
} else if (tee < 4.96757) { |
779 |
|
|
/* mmtau1 */ |
780 |
|
|
tau = (0.0076145275813930356 + tee*(0.24811886965997867 + tee*(0.048329025380584194 + |
781 |
|
|
tee*(0.04227260554167517 + (0.0084221516844712 + 0.0092075782656669*tee)*tee))))/ |
782 |
|
|
(1.0 + tee*(-0.43596678272093764 + tee*(0.38077975530585234 + tee*(-0.049133766853683175 + (0.030319379462443567 + 0.0034126333151669654*tee)*tee)))); |
783 |
✗✓ |
3 |
} else if (tee < 15.4583) { |
784 |
|
|
/* mmtau2 */ |
785 |
|
|
tau = (-0.2897145176074084 + tee*(1.3527948686285203 + tee*(-0.47099157589904095 + |
786 |
|
|
tee*(-0.16031981786376195 + (-0.004820970155881798 - 4.149777202275125e-6*tee)*tee))))/ |
787 |
|
|
(1.0 + tee*(0.3662508612514773 + tee*(-0.5357849572367938 + (-0.0805122462310566 - 0.0015558889784971902*tee)*tee))); |
788 |
✓✗ |
3 |
} else if (tee < 420.787) { |
789 |
|
|
/* mmtau3 */ |
790 |
|
6 |
tau = (-4.2037874383990445e9 + tee*(2.838805157541766e9 + tee*(4.032410315406513e8 + tee*(5.392017876788518e6 + tee*(9135.49750298428 + tee)))))/ |
791 |
|
3 |
(tee*(2.326563899563907e9 + tee*(1.6920560224321905e8 + tee*(1.613645012626063e6 + (2049.748257887103 + 0.1617034516398788*tee)*tee)))); |
792 |
|
|
#else /* quick and dirty approximation */ |
793 |
|
|
} else if (tee < 1.3741310015234351) { |
794 |
|
|
tau = 0.600069568241882*tee/1.3741310015234351; |
795 |
|
|
#endif |
796 |
|
3 |
} else { |
797 |
|
|
/* lindtau = eq (33) in paper */ |
798 |
|
|
tau = 0.53653222368715360118 + log(tee)/2.0 + log(1.0 - 1.0/(8.0*tee)); |
799 |
|
|
} |
800 |
|
6 |
return tau; |
801 |
|
|
} |
802 |
|
|
|
803 |
|
|
double |
804 |
|
|
airTimeOfTau(double tau) { |
805 |
|
|
double tee; |
806 |
|
|
|
807 |
|
|
/* the number of branches here is not good; needs re-working */ |
808 |
✗✓ |
26 |
if (tau < 0) { |
809 |
|
|
tee = 0; |
810 |
|
|
#if ACCURATE |
811 |
|
|
} else |
812 |
✓✓ |
13 |
if (tau < 0.611262) { |
813 |
|
|
/* mmtee0tweaked */ |
814 |
|
8 |
tee = (tau*(3.6275987317285265 + tau*(11.774700160760132 + tau*(4.52406587856803 + tau*(-14.125688866786549 + tau*(-0.725387283317479 + 3.5113122862478865*tau))))))/ |
815 |
|
4 |
(1.0 + tau*(4.955066250765395 + tau*(4.6850073321973404 + tau*(-6.407987550661679 + tau*(-6.398430668865182 + 5.213709282093169*tau))))); |
816 |
✓✓ |
13 |
} else if (tau < 1.31281) { |
817 |
|
|
/* mmtee1 */ |
818 |
|
6 |
tee = (1.9887378739371435e49 + tau*(-2.681749984485673e50 + tau*(-4.23360463718195e50 + tau*(2.09694591123974e51 + tau*(-2.7561518523389087e51 + (1.661629137055526e51 - 4.471073383223687e50*tau)*tau)))))/ |
819 |
|
3 |
(1.0 + tau*(-5.920734745050949e50 + tau*(1.580953446553531e51 + tau*(-1.799463907469813e51 + tau*(1.0766702953985062e51 + tau*(-3.57278667155516e50 + 5.008335824520649e49*tau)))))); |
820 |
✓✓ |
9 |
} else if (tau < 1.64767) { |
821 |
|
|
/* mmtee2 */ |
822 |
|
2 |
tee = (7.929177830383403 + tau*(-26.12773195115971 + tau*(40.13296225515305 + tau*(-25.041659428733585 + 11.357596970027744*tau))))/ |
823 |
|
1 |
(1.0 + tau*(-2.3694595653302377 + tau*(7.324354882915464 + (-3.5335141717471314 + 0.4916661013041915*tau)*tau))); |
824 |
✓✓ |
6 |
} else if (tau < 1.88714) { |
825 |
|
|
/* mmtee3 */ |
826 |
|
2 |
tee = (0.8334252264680793 + tau*(-0.2388940380698891 + (0.6057616935583752 - 0.01610044688317929*tau)*tau))/(1.0 + tau*(-0.7723301124908083 + (0.21283962841683607 - 0.020834957466407206*tau)*tau)); |
827 |
✓✓ |
5 |
} else if (tau < 2.23845) { |
828 |
|
|
/* mmtee4 */ |
829 |
|
1 |
tee = (0.6376900379835665 + tau*(0.3177131886056259 + (0.1844114646774132 + 0.2001613331260136*tau)*tau))/(1.0 + tau*(-0.6685635461372561 + (0.15860524381878136 - 0.013304300252332686*tau)*tau)); |
830 |
✗✓ |
3 |
} else if (tau < 2.6065) { |
831 |
|
|
/* mmtee5 */ |
832 |
|
|
tee = (1.3420027677612982 + (-0.939215712453483 + 0.9586140009249253*tau)*tau)/(1.0 + tau*(-0.6923014141351673 + (0.16834190074776287 - 0.014312833444962668*tau)*tau)); |
833 |
✓✗ |
2 |
} else if (tau < 3.14419) { |
834 |
|
|
/* mmtee6 */ |
835 |
|
2 |
tee = (tau*(190.2181493338235 + tau*(-120.16652155353106 + 60.*tau)))/(76.13355144582292 + tau*(-42.019121363472614 + (8.023304636521623 - 0.5281725039404653*tau)*tau)); |
836 |
|
|
#else /* quick and dirty approximation */ |
837 |
|
|
} else if (tau < 0.600069568241882) { |
838 |
|
|
tee = 1.3741310015234351*tau/0.600069568241882; |
839 |
|
|
#endif |
840 |
|
2 |
} else { |
841 |
|
|
/* lindtee = lindtau^{-1} */ |
842 |
|
|
double ee; |
843 |
|
|
ee = exp(2.0*tau); |
844 |
|
|
tee = 0.0063325739776461107152*(27.0*ee + 2*AIR_PI*AIR_PI + 3.0*sqrt(81.0*ee*ee + 12*ee*AIR_PI*AIR_PI)); |
845 |
|
|
} |
846 |
|
13 |
return tee; |
847 |
|
|
} |
848 |
|
|
|
849 |
|
|
double |
850 |
|
|
airSigmaOfTau(double tau) { |
851 |
|
|
|
852 |
|
26 |
return sqrt(airTimeOfTau(tau)); |
853 |
|
|
} |
854 |
|
|
|
855 |
|
|
double |
856 |
|
|
airTauOfSigma(double sig) { |
857 |
|
|
|
858 |
|
12 |
return airTauOfTime(sig*sig); |
859 |
|
|
} |
860 |
|
|
|
861 |
|
|
/* http://en.wikipedia.org/wiki/Halton_sequences */ |
862 |
|
|
double |
863 |
|
|
airVanDerCorput(unsigned int indx, unsigned int base) { |
864 |
|
|
double result=0.0, ff; |
865 |
|
|
unsigned int ii; |
866 |
|
|
|
867 |
|
|
ff = 1.0/base; |
868 |
|
|
ii = indx; |
869 |
|
|
while (ii) { |
870 |
|
|
result += ff*(ii % base); |
871 |
|
|
ii /= base; |
872 |
|
|
ff /= base; |
873 |
|
|
} |
874 |
|
|
return result; |
875 |
|
|
} |
876 |
|
|
|
877 |
|
|
void |
878 |
|
|
airHalton(double *out, unsigned int indx, |
879 |
|
|
const unsigned int *base, unsigned int num) { |
880 |
|
|
unsigned int nn, bb; |
881 |
|
|
|
882 |
✓✓ |
267300 |
for (nn=0; nn<num; nn++) { |
883 |
|
|
double ff, result = 0.0; |
884 |
|
|
unsigned int ii; |
885 |
|
89100 |
bb = base[nn]; |
886 |
|
89100 |
ff = 1.0/bb; |
887 |
|
|
ii = indx; |
888 |
✓✓ |
1408728 |
while (ii) { |
889 |
|
615264 |
result += ff*(ii % bb); |
890 |
|
615264 |
ii /= bb; |
891 |
|
615264 |
ff /= bb; |
892 |
|
|
} |
893 |
|
89100 |
out[nn] = result; |
894 |
|
|
} |
895 |
|
|
return; |
896 |
|
29700 |
} |
897 |
|
|
|
898 |
|
|
/* via "Table[Prime[n], {n, 1000}]" in Mathematica */ |
899 |
|
|
const unsigned int airPrimeList[AIR_PRIME_NUM] = { |
900 |
|
|
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, |
901 |
|
|
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, |
902 |
|
|
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, |
903 |
|
|
223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, |
904 |
|
|
293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, |
905 |
|
|
383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, |
906 |
|
|
463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, |
907 |
|
|
569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, |
908 |
|
|
647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, |
909 |
|
|
743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, |
910 |
|
|
839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, |
911 |
|
|
941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, |
912 |
|
|
1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, |
913 |
|
|
1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, |
914 |
|
|
1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, |
915 |
|
|
1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, |
916 |
|
|
1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, |
917 |
|
|
1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, |
918 |
|
|
1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, |
919 |
|
|
1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, |
920 |
|
|
1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, |
921 |
|
|
1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, |
922 |
|
|
1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, |
923 |
|
|
1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, |
924 |
|
|
2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, |
925 |
|
|
2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, |
926 |
|
|
2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, |
927 |
|
|
2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, |
928 |
|
|
2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, |
929 |
|
|
2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, |
930 |
|
|
2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, |
931 |
|
|
2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, |
932 |
|
|
2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, |
933 |
|
|
2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, |
934 |
|
|
2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, |
935 |
|
|
2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, |
936 |
|
|
3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, |
937 |
|
|
3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, |
938 |
|
|
3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, |
939 |
|
|
3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, |
940 |
|
|
3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, |
941 |
|
|
3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, |
942 |
|
|
3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, |
943 |
|
|
3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, |
944 |
|
|
3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, |
945 |
|
|
3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, |
946 |
|
|
3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, |
947 |
|
|
4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, |
948 |
|
|
4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, |
949 |
|
|
4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, |
950 |
|
|
4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, |
951 |
|
|
4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, |
952 |
|
|
4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, |
953 |
|
|
4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, |
954 |
|
|
4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, |
955 |
|
|
4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, |
956 |
|
|
4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, |
957 |
|
|
4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, |
958 |
|
|
5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, |
959 |
|
|
5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, |
960 |
|
|
5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, |
961 |
|
|
5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, |
962 |
|
|
5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, |
963 |
|
|
5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, |
964 |
|
|
5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, |
965 |
|
|
5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, |
966 |
|
|
5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, |
967 |
|
|
5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, |
968 |
|
|
6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, |
969 |
|
|
6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, |
970 |
|
|
6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, |
971 |
|
|
6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, |
972 |
|
|
6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, |
973 |
|
|
6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, |
974 |
|
|
6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, |
975 |
|
|
6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, |
976 |
|
|
6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, |
977 |
|
|
6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, |
978 |
|
|
6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, |
979 |
|
|
7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, |
980 |
|
|
7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, |
981 |
|
|
7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, |
982 |
|
|
7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, |
983 |
|
|
7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, |
984 |
|
|
7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, |
985 |
|
|
7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, |
986 |
|
|
7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, |
987 |
|
|
7901, 7907, 7919}; |
988 |
|
|
|
989 |
|
|
/* |
990 |
|
|
** CRC code available in various places, including: |
991 |
|
|
** http://pubs.opengroup.org/onlinepubs/007904875/utilities/cksum.html |
992 |
|
|
** which curiously has no copyright declaration? |
993 |
|
|
*/ |
994 |
|
|
|
995 |
|
|
static unsigned int |
996 |
|
|
crcTable[] = { |
997 |
|
|
0x00000000, |
998 |
|
|
0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, |
999 |
|
|
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, |
1000 |
|
|
0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, |
1001 |
|
|
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, |
1002 |
|
|
0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, |
1003 |
|
|
0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, |
1004 |
|
|
0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, |
1005 |
|
|
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, |
1006 |
|
|
0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, |
1007 |
|
|
0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, |
1008 |
|
|
0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, |
1009 |
|
|
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, |
1010 |
|
|
0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, |
1011 |
|
|
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, |
1012 |
|
|
0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, |
1013 |
|
|
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, |
1014 |
|
|
0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, |
1015 |
|
|
0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, |
1016 |
|
|
0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, |
1017 |
|
|
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, |
1018 |
|
|
0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, |
1019 |
|
|
0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, |
1020 |
|
|
0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, |
1021 |
|
|
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, |
1022 |
|
|
0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, |
1023 |
|
|
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, |
1024 |
|
|
0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, |
1025 |
|
|
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, |
1026 |
|
|
0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, |
1027 |
|
|
0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, |
1028 |
|
|
0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, |
1029 |
|
|
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, |
1030 |
|
|
0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, |
1031 |
|
|
0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, |
1032 |
|
|
0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, |
1033 |
|
|
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, |
1034 |
|
|
0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, |
1035 |
|
|
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, |
1036 |
|
|
0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, |
1037 |
|
|
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, |
1038 |
|
|
0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, |
1039 |
|
|
0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, |
1040 |
|
|
0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, |
1041 |
|
|
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, |
1042 |
|
|
0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, |
1043 |
|
|
0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, |
1044 |
|
|
0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, |
1045 |
|
|
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, |
1046 |
|
|
0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, |
1047 |
|
|
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, |
1048 |
|
|
0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 |
1049 |
|
|
}; |
1050 |
|
|
|
1051 |
|
|
/* note "c" is used once */ |
1052 |
|
|
#define CRC32(crc, c) (crc) = (((crc) << 8) ^ crcTable[((crc) >> 24) ^ (c)]) |
1053 |
|
|
|
1054 |
|
|
unsigned int |
1055 |
|
|
airCRC32(const unsigned char *cdata, size_t len, size_t unit, int swap) { |
1056 |
|
|
unsigned int crc=0; |
1057 |
|
|
size_t ii, jj, nn, mm; |
1058 |
|
|
const unsigned char *crev; |
1059 |
|
|
|
1060 |
✗✓ |
24 |
if (!(cdata && len)) { |
1061 |
|
|
return 0; |
1062 |
|
|
} |
1063 |
✓✗ |
12 |
if (swap) { |
1064 |
|
|
/* if doing swapping, we need make sure we have a unit size, |
1065 |
|
|
and that it divides into len */ |
1066 |
✓✗✗✓
|
24 |
if (!(unit && !(len % unit))) { |
1067 |
|
|
return 0; |
1068 |
|
|
} |
1069 |
|
|
} |
1070 |
|
|
nn = len; |
1071 |
|
|
|
1072 |
✗✓ |
12 |
if (!swap) { |
1073 |
|
|
/* simple case: feed "len" bytes from "cdata" into CRC32 */ |
1074 |
|
|
for (ii=0; ii<nn; ii++) { |
1075 |
|
|
CRC32(crc, *(cdata++)); |
1076 |
|
|
} |
1077 |
|
|
} else { |
1078 |
|
|
/* have to swap, work "unit" bytes at a time, working down |
1079 |
|
|
the bytes within each unit */ |
1080 |
|
12 |
mm = len / unit; |
1081 |
✓✓ |
25466568 |
for (jj=0; jj<mm; jj++) { |
1082 |
|
12733272 |
crev = cdata + jj*unit + unit-1; |
1083 |
✓✓ |
127332720 |
for (ii=0; ii<unit; ii++) { |
1084 |
|
50933088 |
CRC32(crc, *(crev--)); |
1085 |
|
|
} |
1086 |
|
|
} |
1087 |
|
|
} |
1088 |
|
|
|
1089 |
|
|
/* include length of data in result */ |
1090 |
✓✓ |
84 |
for (; nn; nn >>= 8) { |
1091 |
|
36 |
CRC32(crc, (nn & 0xff)); |
1092 |
|
|
} |
1093 |
|
|
|
1094 |
|
12 |
return ~crc; |
1095 |
|
12 |
} |