Mercurial > repos > vipints > rdiff
comparison rDiff/src/locfit/Source/libtube.c @ 0:0f80a5141704
version 0.3 uploaded
author | vipints |
---|---|
date | Thu, 14 Feb 2013 23:38:36 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:0f80a5141704 |
---|---|
1 /* | |
2 * Copyright 1996-2006 Catherine Loader. | |
3 */ | |
4 | |
5 #include "mex.h" | |
6 /* | |
7 * Copyright 1996-2006 Catherine Loader. | |
8 */ | |
9 /* | |
10 * Copyright (c) 1998-2006 Catherine Loader. | |
11 * This file contains functions to compute the constants | |
12 * appearing in the tube formula. | |
13 */ | |
14 | |
15 #include <stdio.h> | |
16 #include <math.h> | |
17 #include "tube.h" | |
18 | |
19 static double *fd, *ft; | |
20 static int globm, (*wdf)(), use_covar, kap_terms; | |
21 | |
22 int k0_reqd(d,n,uc) | |
23 int d, n, uc; | |
24 { int m; | |
25 m = d*(d+1)+1; | |
26 if (uc) return(2*m*m); | |
27 else return(2*n*m); | |
28 } | |
29 | |
30 void assignk0(z,d,n) /* z should be n*(2*d*d+2*d+2); */ | |
31 double *z; | |
32 int d, n; | |
33 { ft = z; z += n*(d*(d+1)+1); | |
34 fd = z; z += n*(d*(d+1)+1); | |
35 } | |
36 | |
37 /* Residual projection of y to the columns of A, | |
38 * (I - A(R^TR)^{-1}A^T)y | |
39 * R should be from the QR-decomp. of A. | |
40 */ | |
41 void rproject(y,A,R,n,p) | |
42 double *y, *A, *R; | |
43 int n, p; | |
44 { double v[1+TUBE_MXDIM]; | |
45 int i, j; | |
46 | |
47 for (i=0; i<p; i++) v[i] = innerprod(&A[i*n],y,n); | |
48 qrsolv(R,v,n,p); | |
49 for (i=0; i<n; i++) | |
50 for (j=0; j<p; j++) | |
51 y[i] -= A[j*n+i]*v[j]; | |
52 } | |
53 | |
54 double k2c(lij,A,m,dd,d) | |
55 double *lij, *A; | |
56 int m, d, dd; | |
57 { int i, j, k, l; | |
58 double sum, *bk, v[TUBE_MXDIM]; | |
59 | |
60 for (i=0; i<dd*d; i++) | |
61 chol_hsolve(fd,&lij[i*m],m,dd+1); | |
62 for (i=0; i<dd*d; i++) | |
63 for (j=0; j<dd*d; j++) | |
64 lij[i*m+j+d+1] -= innerprod(&lij[i*m],&lij[j*m],dd+1); | |
65 | |
66 sum = 0; | |
67 for (i=0; i<dd; i++) | |
68 for (j=0; j<i; j++) | |
69 { bk = &lij[i*d*m + j*d + d+1]; | |
70 for (k=0; k<dd; k++) | |
71 { v[0] = 0; | |
72 for (l=0; l<dd; l++) v[l+1] = bk[k*m+l]; | |
73 chol_solve(fd,v,m,dd+1); | |
74 for (l=0; l<dd; l++) bk[k*m+l] = v[l+1]; | |
75 } | |
76 for (k=0; k<dd; k++) | |
77 { v[0] = 0; | |
78 for (l=0; l<dd; l++) v[l+1] = bk[l*m+k]; | |
79 chol_solve(fd,v,m,dd+1); | |
80 for (l=0; l<dd; l++) bk[l*m+k] = v[l+1]; | |
81 } | |
82 sum += bk[i*m+j] - bk[j*m+i]; | |
83 } | |
84 return(sum*fd[0]*fd[0]); | |
85 } | |
86 | |
87 double k2x(lij,A,m,d,dd) | |
88 double *lij, *A; | |
89 int m, d, dd; | |
90 { int i, j, k; | |
91 double s, v[1+TUBE_MXDIM], *ll; | |
92 | |
93 /* residual projections of lij onto A = [l,l1,...,ld] */ | |
94 for (i=0; i<d; i++) | |
95 for (j=i; j<d; j++) | |
96 { ll = &lij[(i*dd+j)*m]; | |
97 rproject(ll,A,fd,m,d+1); | |
98 if (i!=j) memcpy(&lij[(j*dd+i)*m],ll,m*sizeof(double)); | |
99 } | |
100 | |
101 /* compute lij[j][i] = e_i^T (A^T A)^{-1} B_j^T */ | |
102 for (k=0; k<m; k++) | |
103 for (j=0; j<d; j++) | |
104 { v[0] = 0; | |
105 for (i=0; i<d; i++) v[i+1] = lij[(j*dd+i)*m+k]; | |
106 qrsolv(fd,v,m,d+1); | |
107 for (i=0; i<d; i++) lij[(j*dd+i)*m+k] = v[i+1]; | |
108 } | |
109 | |
110 /* finally, add up to get the kappa2 term */ | |
111 s = 0; | |
112 for (j=0; j<d; j++) | |
113 for (k=0; k<j; k++) | |
114 s += innerprod(&lij[(j*dd+j)*m],&lij[(k*dd+k)*m],m) | |
115 - innerprod(&lij[(j*dd+k)*m],&lij[(k*dd+j)*m],m); | |
116 | |
117 return(s*fd[0]*fd[0]); | |
118 } | |
119 | |
120 void d2c(ll,nn,li,ni,lij,nij,M,m,dd,d) | |
121 double *ll, *nn, *li, *ni, *lij, *nij, *M; | |
122 int m, dd, d; | |
123 { int i, j, k, l, t, u, v, w; | |
124 double z; | |
125 | |
126 for (i=0; i<dd; i++) | |
127 for (j=0; j<dd; j++) | |
128 { for (k=0; k<d; k++) | |
129 { for (l=0; l<d; l++) | |
130 { z = M[i*d+k]*M[j*d+l]; | |
131 if (z != 0.0) | |
132 { nij[(i*d+j)*m] += z*lij[(k*d+l)*m]; | |
133 for (t=0; t<d; t++) /* need d, not dd here */ | |
134 for (u=0; u<d; u++) | |
135 nij[(i*d+j)*m+t+1] += z*M[t*d+u]*lij[(k*d+l)*m+u+1]; | |
136 for (t=0; t<dd; t++) | |
137 for (u=0; u<dd; u++) | |
138 { for (v=0; v<d; v++) | |
139 for (w=0; w<d; w++) | |
140 nij[(i*d+j)*m+(t*d+u)+d+1] += | |
141 z*M[t*d+v]*M[u*d+w]*lij[(k*d+l)*m+(v*d+w)+d+1]; | |
142 for (v=0; v<d; v++) | |
143 nij[(i*d+j)*m+(t*d+u)+d+1] += z*M[(v+1)*d*d+t*d+u]*lij[(k*d+l)*m+v+1]; | |
144 } | |
145 } | |
146 } | |
147 | |
148 z = M[(k+1)*d*d+i*d+j]; | |
149 if (z!=0.0) | |
150 { nij[(i*d+j)*m] += z*li[k*m]; | |
151 for (t=0; t<d; t++) | |
152 for (u=0; u<d; u++) | |
153 nij[(i*d+j)*m+t+1] += z*M[t*d+u]*li[k*m+u+1]; | |
154 for (t=0; t<dd; t++) | |
155 for (u=0; u<dd; u++) | |
156 { for (v=0; v<d; v++) | |
157 for (w=0; w<d; w++) | |
158 nij[(i*d+j)*m+(t*d+u)+d+1] += z*M[t*d+v]*M[u*d+w]*lij[(v*d+w)*m+k+1]; | |
159 for (v=0; v<d; v++) | |
160 nij[(i*d+j)*m+(t*d+u)+d+1] += z*M[(v+1)*d*d+t*d+u]*li[k*m+v+1]; | |
161 } | |
162 } | |
163 } | |
164 } | |
165 } | |
166 | |
167 void d2x(li,lij,nij,M,m,dd,d) | |
168 double *li, *lij, *nij, *M; | |
169 int m, dd, d; | |
170 { int i, j, k, l, z; | |
171 double t; | |
172 for (i=0; i<dd; i++) | |
173 for (j=0; j<dd; j++) | |
174 { for (k=0; k<d; k++) | |
175 { for (l=0; l<d; l++) | |
176 { t = M[i*d+k] * M[j*d+l]; | |
177 if (t != 0.0) | |
178 { for (z=0; z<m; z++) | |
179 nij[(i*d+j)*m+z] += t*lij[(k*d+l)*m+z]; | |
180 } | |
181 } | |
182 t = M[(k+1)*d*d+i*d+j]; | |
183 if (t!=0.0) | |
184 for (z=0; z<m; z++) | |
185 nij[(i*d+j)*m+z] += t*li[k*m+z]; | |
186 } | |
187 } | |
188 } | |
189 | |
190 int k0x(x,d,kap,M) | |
191 double *x, *kap, *M; | |
192 int d; | |
193 { double det, *lij, *nij, z; | |
194 int j, m, r; | |
195 | |
196 r = 1 + ((d>=2) & (kap_terms >= 3)); | |
197 m = globm = wdf(x,ft,r); | |
198 | |
199 memcpy(fd,ft,m*(d+1)*sizeof(double)); | |
200 if (use_covar) chol_dec(fd,m,d+1); | |
201 else qr(fd,m,d+1,NULL); | |
202 | |
203 det = 1; | |
204 for (j=1; j<=d; j++) | |
205 det *= fd[j*(m+1)]/fd[0]; | |
206 kap[0] = det; | |
207 if (kap_terms == 1) return(1); | |
208 kap[1] = 0.0; | |
209 if ((kap_terms == 2) | (d<=1)) return(2); | |
210 | |
211 lij = &ft[(d+1)*m]; | |
212 nij = &fd[(d+1)*m]; | |
213 memcpy(nij,lij,m*d*d*sizeof(double)); | |
214 z = (use_covar) ? k2c(nij,ft,m,d,d) : k2x(nij,ft,m,d,d); | |
215 kap[2] = z*det; | |
216 if ((kap_terms == 3) | (d==2)) return(3); | |
217 | |
218 kap[3] = 0; | |
219 return(4); | |
220 } | |
221 | |
222 void d1c(li,ni,m,d,M) | |
223 double *li, *ni, *M; | |
224 int m, d; | |
225 { int i, j, k, l; | |
226 double t; | |
227 | |
228 fd[0] = ft[0]; | |
229 for (i=0; i<d; i++) | |
230 { t = 0; | |
231 for (j=0; j<d; j++) t += M[i*d+j]*li[j*m]; | |
232 fd[i+1] = ni[i*m] = t; | |
233 | |
234 for (j=0; j<d; j++) | |
235 { t = 0; | |
236 for (k=0; k<d; k++) | |
237 for (l=0; l<d; l++) | |
238 t += li[k*m+l+1] * M[i*d+k] * M[j*d+l]; | |
239 ni[i*m+j+1] = t; | |
240 } | |
241 } | |
242 } | |
243 | |
244 void d1x(li,ni,m,d,M) | |
245 double *li, *ni, *M; | |
246 int m, d; | |
247 { int i, j, k; | |
248 memcpy(fd,ft,m*sizeof(double)); | |
249 setzero(ni,m*d); | |
250 for (j=0; j<d; j++) | |
251 for (k=0; k<d; k++) | |
252 if (M[j*d+k]!=0) | |
253 for (i=0; i<m; i++) ni[j*m+i] += M[j*d+k]*li[k*m+i]; | |
254 } | |
255 | |
256 int l1x(x,d,lap,M) | |
257 double *x, *lap, *M; | |
258 int d; | |
259 { double det, sumcj, *u, v[TUBE_MXDIM]; | |
260 double *ll, *li, *lij, *ni, *nij; | |
261 int i, j, m; | |
262 if (kap_terms<=1) return(0); | |
263 m = globm; | |
264 li = &ft[m]; lij = &ft[(d+1)*m]; | |
265 ni = &fd[m]; nij = &fd[(d+1)*m]; | |
266 setzero(ni,m*d); | |
267 setzero(nij,m*d*d); | |
268 | |
269 if (use_covar) d1c(li,ni,m,d,M); | |
270 else d1x(li,ni,m,d,M); | |
271 | |
272 /* the last (d+1) columns of nij are free, use for an extra copy of ni */ | |
273 ll = &fd[d*d*m]; | |
274 u = &ll[d*m]; | |
275 if (use_covar) | |
276 memcpy(u,&ni[(d-1)*m],d*sizeof(double)); /* cov(ld, (l,l1,...ld-1)) */ | |
277 else | |
278 memcpy(ll,fd,(d+1)*m*sizeof(double)); | |
279 | |
280 if (use_covar) chol_dec(fd,m,d+1); | |
281 else qr(fd,m,d+1,NULL); | |
282 det = 1; | |
283 for (j=1; j<d; j++) | |
284 det *= fd[(m+1)*j]/fd[0]; | |
285 lap[0] = det; | |
286 if ((kap_terms==2) | (d<=1)) return(1); | |
287 | |
288 sumcj = 0.0; | |
289 if (use_covar) | |
290 { d2c(ft,fd,li,ni,lij,nij,M,m,d-1,d); | |
291 chol_solve(fd,u,m,d); | |
292 for (i=0; i<d-1; i++) | |
293 { v[0] = 0; | |
294 for (j=0; j<d-1; j++) | |
295 v[j+1] = nij[(i*d+j)*m+d] - innerprod(u,&nij[(i*d+j)*m],d); | |
296 chol_solve(fd,v,m,d); | |
297 sumcj -= v[i+1]; | |
298 } | |
299 } | |
300 else | |
301 { d2x(li,lij,nij,M,m,d-1,d); | |
302 rproject(u,ll,fd,m,d); | |
303 for (i=0; i<d-1; i++) | |
304 { v[0] = 0; | |
305 for (j=0; j<d-1; j++) v[j+1] = innerprod(&nij[(i*d+j)*m],u,m); | |
306 qrsolv(fd,v,m,d); | |
307 sumcj -= v[i+1]; | |
308 } | |
309 } | |
310 | |
311 lap[1] = sumcj*det*fd[0]/fd[(m+1)*d]; | |
312 if ((kap_terms==3) | (d==2)) return(2); | |
313 | |
314 if (use_covar) lap[2] = k2c(nij,ll,m,d-1,d)*det; | |
315 else lap[2] = k2x(nij,ll,m,d-1,d)*det; | |
316 return(3); | |
317 } | |
318 | |
319 int m0x(x,d,m0,M) | |
320 double *x, *m0, *M; | |
321 int d; | |
322 { double det, *li, *ni, *lij, *nij, *ll, *u1, *u2; | |
323 double om, so, co, sumcj, v[TUBE_MXDIM]; | |
324 int m, i, j; | |
325 | |
326 if ((kap_terms<=2) | (d<=1)) return(0); | |
327 | |
328 m = globm; | |
329 li = &ft[m]; lij = &ft[(d+1)*m]; | |
330 ni = &fd[m]; nij = &fd[(d+1)*m]; | |
331 setzero(ni,m*d); | |
332 setzero(nij,m*d*d); | |
333 | |
334 if (use_covar) d1c(li,ni,m,d,M); | |
335 else d1x(li,ni,m,d,M); | |
336 | |
337 /* the last (d+1) columns of nij are free, use for an extra copy of ni */ | |
338 ll = &fd[d*d*m]; | |
339 u1 = &ll[d*m]; | |
340 u2 = &ll[(d-1)*m]; | |
341 if (use_covar) | |
342 { memcpy(u1,&ni[(d-1)*m],d*sizeof(double)); | |
343 memcpy(u2,&ni[(d-2)*m],d*sizeof(double)); | |
344 } | |
345 else | |
346 memcpy(ll,fd,(d+1)*m*sizeof(double)); | |
347 | |
348 if (use_covar) chol_dec(fd,m,d+1); | |
349 else qr(fd,m,d+1,NULL); | |
350 det = 1; | |
351 for (j=1; j<d-1; j++) | |
352 det *= fd[j*(m+1)]/fd[0]; | |
353 om = atan2(fd[d*(m+1)],-fd[d*(m+1)-1]); | |
354 m0[0] = det*om; | |
355 if ((kap_terms==3) | (d==2)) return(1); | |
356 | |
357 so = sin(om)/fd[d*(m+1)]; | |
358 co = (1-cos(om))/fd[(d-1)*(m+1)]; | |
359 sumcj = 0.0; | |
360 if (use_covar) | |
361 { d2c(ft,fd,li,ni,lij,nij,M,m,d-2,d); | |
362 chol_solve(fd,u1,m,d); | |
363 chol_solve(fd,u2,m,d-1); | |
364 for (i=0; i<d-2; i++) | |
365 { v[0] = 0; | |
366 for (j=0; j<d-2; j++) | |
367 v[j+1] = | |
368 so*(nij[(i*d+j)*m+d]-innerprod(u1,&nij[(i*d+j)*m],d)) | |
369 +co*(nij[(i*d+j)*m+d-1]-innerprod(u2,&nij[(i*d+j)*m],d-1)); | |
370 qrsolv(fd,v,m,d-1); | |
371 sumcj -= v[i+1]; | |
372 } | |
373 } | |
374 else | |
375 { d2x(li,lij,nij,M,m,d-2,d); | |
376 rproject(u1,ll,fd,m,d); | |
377 rproject(u2,ll,fd,m,d-1); /* now, u1, u2 are unnormalized n1*, n2* */ | |
378 for (i=0; i<m; i++) | |
379 u1[i] = so*u1[i] + co*u2[i]; /* for n1*, n2* */ | |
380 for (i=0; i<d-2; i++) | |
381 { v[0] = 0; | |
382 for (j=0; j<d-2; j++) | |
383 v[j+1] = innerprod(&nij[(i*d+j)*m],u1,m); | |
384 qrsolv(fd,v,m,d-1); | |
385 sumcj -= v[i+1]; | |
386 } | |
387 } | |
388 | |
389 m0[1] = sumcj*det*fd[0]; | |
390 return(2); | |
391 } | |
392 | |
393 int n0x(x,d,n0,M) | |
394 double *x, *n0, *M; | |
395 int d; | |
396 { double det, *li, *ni, *a0, *a1, *a2; | |
397 int j, m; | |
398 | |
399 if ((kap_terms <= 3) | (d <= 2)) return(0); | |
400 | |
401 m = globm; | |
402 li = &ft[m]; | |
403 ni = &fd[m]; | |
404 | |
405 if (use_covar) d1c(li,ni,m,d,M); | |
406 else d1x(li,ni,m,d,M); | |
407 | |
408 det = 1; | |
409 if (use_covar) chol_dec(fd,m,d+1); | |
410 else qr(fd,m,d+1,NULL); | |
411 for (j=1; j<d-2; j++) | |
412 det *= fd[j*(m+1)]/fd[0]; | |
413 | |
414 a0 = &ni[(d-3)*m+d-2]; | |
415 a1 = &ni[(d-2)*m+d-2]; | |
416 a2 = &ni[(d-1)*m+d-2]; | |
417 | |
418 a0[0] = a1[1]*a2[2]; | |
419 a0[1] =-a1[0]*a2[2]; | |
420 a0[2] = a1[0]*a2[1]-a1[1]*a2[0]; | |
421 a1[0] = 0; | |
422 a1[1] = a2[2]; | |
423 a1[2] =-a2[1]; | |
424 a2[0] = a2[1] = 0.0; a2[2] = 1.0; | |
425 rn3(a0); rn3(a1); | |
426 n0[0] = det*sptarea(a0,a1,a2); | |
427 return(1); | |
428 } | |
429 | |
430 int kodf(ll,ur,mg,kap,lap) | |
431 double *ll, *ur, *kap, *lap; | |
432 int *mg; | |
433 { double x[1], *l0, *l1, t, sum; | |
434 int i, j, n; | |
435 | |
436 sum = 0.0; | |
437 for (i=0; i<=mg[0]; i++) | |
438 { if (i&1) { l1 = fd; l0 = ft; } | |
439 else { l1 = ft; l0 = fd; } | |
440 x[0] = ll[0] + (ur[0]-ll[0])*i/mg[0]; | |
441 n = wdf(x,l0,0); | |
442 | |
443 t = sqrt(innerprod(l0,l0,n)); | |
444 for (j=0; j<n; j++) l0[j] /= t; | |
445 | |
446 if (i>0) | |
447 { t = 0.0; | |
448 for (j=0; j<n; j++) t += (l1[j]-l0[j])*(l1[j]-l0[j]); | |
449 sum += 2*asin(sqrt(t)/2); | |
450 } | |
451 } | |
452 kap[0] = sum; | |
453 if (kap_terms<=1) return(1); | |
454 kap[1] = 0.0; | |
455 lap[0] = 2.0; | |
456 return(2); | |
457 } | |
458 | |
459 int tube_constants(f,d,m,ev,mg,fl,kap,wk,terms,uc) | |
460 double *fl, *kap, *wk; | |
461 int d, m, ev, *mg, (*f)(), terms, uc; | |
462 { int aw, deb=0; | |
463 double k0[4], l0[3], m0[2], n0[1], z[TUBE_MXDIM]; | |
464 | |
465 wdf = f; | |
466 | |
467 aw = (wk==NULL); | |
468 if (aw) { | |
469 wk = (double *)calloc(k0_reqd(d,m,uc),sizeof(double)); | |
470 if ( wk == NULL ) { | |
471 printf("Problem allocating memory for wk\n");fflush(stdout); | |
472 } | |
473 } | |
474 assignk0(wk,d,m); | |
475 | |
476 k0[0] = k0[1] = k0[2] = k0[3] = 0.0; | |
477 l0[0] = l0[1] = l0[2] = 0.0; | |
478 m0[0] = m0[1] = 0.0; | |
479 n0[0] = 0.0; | |
480 | |
481 use_covar = uc; | |
482 kap_terms = terms; | |
483 if ((kap_terms <=0) | (kap_terms >= 5)) | |
484 mut_printf("Warning: terms = %2d\n",kap_terms); | |
485 | |
486 switch(ev) | |
487 { | |
488 case IMONTE: | |
489 monte(k0x,fl,&fl[d],d,k0,mg[0]); | |
490 break; | |
491 case ISPHERIC: | |
492 if (d==2) integ_disc(k0x,l1x,fl,k0,l0,mg); | |
493 if (d==3) integ_sphere(k0x,l1x,fl,k0,l0,mg); | |
494 break; | |
495 case ISIMPSON: | |
496 if (use_covar) simpson4(k0x,l1x,m0x,n0x,fl,&fl[d],d,k0,l0,m0,n0,mg,z); | |
497 else simpson4(k0x,l1x,m0x,n0x,fl,&fl[d],d,k0,l0,m0,n0,mg,z); | |
498 break; | |
499 case IDERFREE: | |
500 kodf(fl,&fl[d],mg,k0,l0); | |
501 break; | |
502 default: | |
503 mut_printf("Unknown integration type in tube_constants().\n"); | |
504 } | |
505 | |
506 if (deb>0) | |
507 { mut_printf("constants:\n"); | |
508 mut_printf(" k0: %8.5f %8.5f %8.5f %8.5f\n",k0[0],k0[1],k0[2],k0[3]); | |
509 mut_printf(" l0: %8.5f %8.5f %8.5f\n",l0[0],l0[1],l0[2]); | |
510 mut_printf(" m0: %8.5f %8.5f\n",m0[0],m0[1]); | |
511 mut_printf(" n0: %8.5f\n",n0[0]); | |
512 if (d==2) mut_printf(" check: %8.5f\n",(k0[0]+k0[2]+l0[1]+m0[0])/(2*PI)); | |
513 if (d==3) mut_printf(" check: %8.5f\n",(l0[0]+l0[2]+m0[1]+n0[0])/(4*PI)); | |
514 } | |
515 | |
516 if (aw) free(wk); | |
517 | |
518 kap[0] = k0[0]; | |
519 if (kap_terms==1) return(1); | |
520 kap[1] = l0[0]/2; | |
521 if ((kap_terms==2) | (d==1)) return(2); | |
522 kap[2] = (k0[2]+l0[1]+m0[0])/(2*PI); | |
523 if ((kap_terms==3) | (d==2)) return(3); | |
524 kap[3] = (l0[2]+m0[1]+n0[0])/(4*PI); | |
525 return(4); | |
526 } | |
527 /* | |
528 * Copyright 1996-2006 Catherine Loader. | |
529 */ | |
530 /* | |
531 * Copyright (c) 1998-2006 Catherine Loader. | |
532 * | |
533 * Computes the critical values from constants kappa0 etc | |
534 * and significance level. | |
535 */ | |
536 | |
537 #include <math.h> | |
538 #include "tube.h" | |
539 | |
540 #define LOGPI 1.144729885849400174143427 | |
541 | |
542 /* area(d) = 2 pi^(d/2) / Gamma(d/2) | |
543 * = surface area of unit sphere in R^d | |
544 */ | |
545 static double A[10] = | |
546 { 1, /* d=0, whatever */ | |
547 2, | |
548 6.2831853071795864770, /* 2*pi */ | |
549 12.566370614359172954, /* 4*pi */ | |
550 19.739208802178717238, /* 2*pi^2 */ | |
551 26.318945069571622985, /* 8/3*pi^2 */ | |
552 31.006276680299820177, /* pi^3 */ | |
553 33.073361792319808190, /* 16/15*pi^3 */ | |
554 32.469697011334145747, /* 1/3*pi^4 */ | |
555 29.686580124648361825 /* 32/105*pi^4 */ | |
556 }; | |
557 | |
558 double area(d) | |
559 int d; | |
560 { if (d<10) return(A[d]); | |
561 return(2*exp(d*LOGPI/2.0-mut_lgammai(d))); | |
562 } | |
563 | |
564 double tailp_uniform(c,k0,m,d,s,n) | |
565 double c, *k0, n; | |
566 int m, d, s; | |
567 { int i; | |
568 double p; | |
569 p = 0.0; | |
570 for (i=0; i<m; i++) if (k0[i] != 0.0) | |
571 p += k0[i] * ibeta(1-c*c,(n-d+i-1)/2.0,(d+1-i)/2.0) / area(d+1-i); | |
572 return( (s==TWO_SIDED) ? 2*p : p ); | |
573 } | |
574 | |
575 double tailp_gaussian(c,k0,m,d,s,n) | |
576 double c, *k0, n; | |
577 int m, d, s; | |
578 { int i; | |
579 double p; | |
580 p = 0.0; | |
581 for (i=0; i<m; i++) if (k0[i] != 0.0) | |
582 p += k0[i] * (1-pchisq(c*c,(double) d+1-i)) / area(d+1-i); | |
583 return( (s==TWO_SIDED) ? 2*p : p ); | |
584 } | |
585 | |
586 double tailp_tprocess(c,k0,m,d,s,n) | |
587 double c, *k0, n; | |
588 int m, d, s; | |
589 { int i; | |
590 double p; | |
591 p = 0.0; | |
592 for (i=0; i<m; i++) if (k0[i] != 0.0) | |
593 p += k0[i] * (1-pf(c*c/(d+1-i),(double) d+1-i, n)) / area(d+1-i); | |
594 return( (s==TWO_SIDED) ? 2*p : p ); | |
595 } | |
596 | |
597 double taild_uniform(c,k0,m,d,s,n) | |
598 double c, *k0, n; | |
599 int m, d, s; | |
600 { int i; | |
601 double p; | |
602 p = 0.0; | |
603 for (i=0; i<m; i++) if (k0[i] != 0.0) | |
604 p += k0[i] * 2*c*dbeta(1-c*c,(n-d+i-1)/2.0,(d+1-i)/2.0,0) / area(d+1-i); | |
605 return( (s==TWO_SIDED) ? 2*p : p ); | |
606 } | |
607 | |
608 double taild_gaussian(c,k0,m,d,s,n) | |
609 double c, *k0, n; | |
610 int m, d, s; | |
611 { int i; | |
612 double p; | |
613 p = 0.0; | |
614 for (i=0; i<m; i++) if (k0[i] != 0.0) | |
615 p += k0[i] * 2*c*dchisq(c*c,(double) d+1-i,0) / area(d+1-i); | |
616 return( (s==TWO_SIDED) ? 2*p : p ); | |
617 } | |
618 | |
619 double taild_tprocess(c,k0,m,d,s,n) | |
620 double c, *k0, n; | |
621 int m, d, s; | |
622 { int i; | |
623 double p; | |
624 p = 0.0; | |
625 for (i=0; i<m; i++) if (k0[i] != 0.0) | |
626 p += k0[i] * 2*c*df(c*c/(d+1-i),(double) d+1-i, n,0) / ((d+1-i)*area(d+1-i)); | |
627 return( (s==TWO_SIDED) ? 2*p : p ); | |
628 } | |
629 | |
630 double tailp(c,k0,m,d,s,nu, process) | |
631 double c, *k0, nu; | |
632 int m, d, s, process; | |
633 { switch(process) | |
634 { case UNIF: return(tailp_uniform(c,k0,m,d,s,nu)); | |
635 case GAUSS: return(tailp_gaussian(c,k0,m,d,s,nu)); | |
636 case TPROC: return(tailp_tprocess(c,k0,m,d,s,nu)); | |
637 } | |
638 mut_printf("taild: unknown process.\n"); | |
639 return(0.0); | |
640 } | |
641 | |
642 double taild(c,k0,m,d,s,nu, process) | |
643 double c, *k0, nu; | |
644 int m, d, s, process; | |
645 { switch(process) | |
646 { case UNIF: return(taild_uniform(c,k0,m,d,s,nu)); | |
647 case GAUSS: return(taild_gaussian(c,k0,m,d,s,nu)); | |
648 case TPROC: return(taild_tprocess(c,k0,m,d,s,nu)); | |
649 } | |
650 mut_printf("taild: unknown process.\n"); | |
651 return(0.0); | |
652 } | |
653 | |
654 double critval(alpha,k0,m,d,s,nu,process) | |
655 double alpha, *k0, nu; | |
656 int m, d, s, process; | |
657 { double c, cn, c0, c1, tp, td; | |
658 int j, maxit; | |
659 double (*tpf)(), (*tdf)(); | |
660 | |
661 maxit = 20; | |
662 if (m<0) | |
663 { mut_printf("critval: no terms?\n"); | |
664 return(2.0); | |
665 } | |
666 if (m>d+1) m = d+1; | |
667 if ((alpha<=0) | (alpha>=1)) | |
668 { mut_printf("critval: invalid alpha %8.5f\n",alpha); | |
669 return(2.0); | |
670 } | |
671 if (alpha>0.5) | |
672 mut_printf("critval: A mighty large tail probability alpha=%8.5f\n",alpha); | |
673 if (m==0) { d = 0; k0[0] = 1; m = 1; } | |
674 | |
675 switch(process) | |
676 { case UNIF: | |
677 c = 0.5; c0 = 0.0; c1 = 1.0; | |
678 tpf = tailp_uniform; | |
679 tdf = taild_uniform; | |
680 break; | |
681 case GAUSS: | |
682 c = 2.0; c0 = 0.0; c1 = 0.0; | |
683 tpf = tailp_gaussian; | |
684 tdf = taild_gaussian; | |
685 break; | |
686 case TPROC: | |
687 c = 2.0; c0 = 0.0; c1 = 0.0; | |
688 tpf = tailp_tprocess; | |
689 tdf = taild_tprocess; | |
690 break; | |
691 default: | |
692 mut_printf("critval: unknown process.\n"); | |
693 return(0.0); | |
694 } | |
695 | |
696 for (j=0; j<maxit; j++) | |
697 { tp = tpf(c,k0,m,d,s,nu)-alpha; | |
698 td = tdf(c,k0,m,d,s,nu); | |
699 if (tp>0) c0 = c; | |
700 if (tp<0) c1 = c; | |
701 cn = c + tp/td; | |
702 if (cn<c0) cn = (c+c0)/2; | |
703 if ((c1>0.0) && (cn>c1)) cn = (c+c1)/2; | |
704 c = cn; | |
705 if (fabs(tp/alpha)<1.0e-10) return(c); | |
706 } | |
707 return(c); | |
708 } |