Mercurial > repos > vipints > rdiff
comparison rDiff/src/locfit/Source/liblfev.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 #include "lfev.h" | |
10 | |
11 extern void fitoptions(); | |
12 | |
13 static double hmin, gmin, sig2, pen, vr, tb; | |
14 static lfit *blf; | |
15 static design *bdes; | |
16 | |
17 int procvbind(des,lf,v) | |
18 design *des; | |
19 lfit *lf; | |
20 int v; | |
21 { double s0, s1, bi; | |
22 int i, ii, k; | |
23 k = procv_var(des,lf,v); | |
24 wdiag(&lf->lfd, &lf->sp, des,des->wd,&lf->dv,0,1,0); | |
25 s0 = s1 = 0.0; | |
26 for (i=0; i<des->n; i++) | |
27 { ii = des->ind[i]; | |
28 s0+= prwt(&lf->lfd,ii)*des->wd[i]*des->wd[i]; | |
29 bi = prwt(&lf->lfd,ii)*fabs(des->wd[i]*ipower(dist(des,ii),deg(&lf->sp)+1)); | |
30 s1+= bi*bi; | |
31 } | |
32 vr += s0; | |
33 tb += s1; | |
34 return(k); | |
35 } | |
36 | |
37 double bcri(h,c,cri) | |
38 double h; | |
39 int c, cri; | |
40 { double num, den, res[10]; | |
41 int (*pv)(); | |
42 if (c==DALP) | |
43 blf->sp.nn = h; | |
44 else | |
45 blf->sp.fixh = h; | |
46 if ((cri&63)==BIND) | |
47 { pv = procvbind; | |
48 vr = tb = 0.0; | |
49 } | |
50 else pv = procvstd; | |
51 if (cri<64) startlf(bdes,blf,pv,0); | |
52 switch(cri&63) | |
53 { case BGCV: | |
54 ressumm(blf,bdes,res); | |
55 num = -2*blf->lfd.n*res[0]; | |
56 den = blf->lfd.n-res[1]; | |
57 return(num/(den*den)); | |
58 case BCP: | |
59 ressumm(blf,bdes,res); | |
60 return(-2*res[0]/sig2-blf->lfd.n+pen*res[1]); | |
61 case BIND: | |
62 return(vr+pen*pen*tb); | |
63 } | |
64 LERR(("bcri: unknown criterion")); | |
65 return(0.0); | |
66 } | |
67 | |
68 void bsel2(h0,g0,ifact,c,cri) | |
69 double h0, g0, ifact; | |
70 int c, cri; | |
71 { int done, inc; | |
72 double h1, g1; | |
73 h1 = h0; g1 = g0; | |
74 done = inc = 0; | |
75 while (!done) | |
76 { h1 *= 1+ifact; | |
77 g0 = g1; | |
78 g1 = bcri(h1,c,cri); | |
79 if (g1<gmin) { hmin = h1; gmin = g1; } | |
80 if (g1>g0) inc++; else inc = 0; | |
81 switch(cri) | |
82 { case BIND: | |
83 done = (inc>=4) & (vr<blf->fp.nv); | |
84 break; | |
85 default: | |
86 done = (inc>=4); | |
87 } | |
88 } | |
89 } | |
90 | |
91 void bsel3(h0,g0,ifact,c,cri) | |
92 double h0, g0, ifact; | |
93 int c, cri; | |
94 { double h1, g1; | |
95 int i; | |
96 hmin = h0; gmin = g0; | |
97 for (i=-1; i<=1; i++) if (i!=0) | |
98 { h1 = h0*(1+i*ifact); | |
99 g1 = bcri(h1,c,cri); | |
100 if (g1<gmin) { hmin = h1; gmin = g1; } | |
101 } | |
102 return; | |
103 } | |
104 | |
105 void bselect(lf,des,c,cri,pn) | |
106 lfit *lf; | |
107 design *des; | |
108 int c, cri; | |
109 double pn; | |
110 { double h0, g0, ifact; | |
111 int i; | |
112 pen = pn; | |
113 blf = lf; | |
114 bdes = des; | |
115 if (cri==BIND) pen /= factorial(deg(&lf->sp)+1); | |
116 hmin = h0 = (c==DFXH) ? fixh(&lf->sp) : nn(&lf->sp); | |
117 if (h0==0) LERR(("bselect: initial bandwidth is 0")); | |
118 if (lf_error) return; | |
119 sig2 = 1.0; | |
120 | |
121 gmin = g0 = bcri(h0,c,cri); | |
122 if (cri==BCP) | |
123 { sig2 = rv(&lf->fp); | |
124 g0 = gmin = bcri(h0,c,cri+64); | |
125 } | |
126 | |
127 ifact = 0.3; | |
128 bsel2(h0,g0,ifact,c,cri); | |
129 | |
130 for (i=0; i<5; i++) | |
131 { ifact = ifact/2; | |
132 bsel3(hmin,gmin,ifact,c,cri); | |
133 } | |
134 if (c==DFXH) | |
135 fixh(&lf->sp) = hmin; | |
136 else | |
137 nn(&lf->sp) = hmin; | |
138 startlf(des,lf,procvstd,0); | |
139 ressumm(lf,des,lf->fp.kap); | |
140 } | |
141 | |
142 double compsda(x,h,n) | |
143 double *x, h; | |
144 int n; | |
145 /* n/(n-1) * int( fhat''(x)^2 dx ); bandwidth h */ | |
146 { int i, j; | |
147 double ik, sd, z; | |
148 ik = wint(1,NULL,0,WGAUS); | |
149 sd = 0; | |
150 | |
151 for (i=0; i<n; i++) | |
152 for (j=i; j<n; j++) | |
153 { z = (x[i]-x[j])/h; | |
154 sd += (2-(i==j))*Wconv4(z,WGAUS)/(ik*ik); | |
155 } | |
156 sd = sd/(n*(n-1)*h*h*h*h*h); | |
157 return(sd); | |
158 } | |
159 | |
160 double widthsj(x,lambda,n) | |
161 double *x, lambda; | |
162 int n; | |
163 { double ik, a, b, td, sa, z, c, c1, c2, c3; | |
164 int i, j; | |
165 a = GFACT*0.920*lambda*exp(-log((double)n)/7)/SQRT2; | |
166 b = GFACT*0.912*lambda*exp(-log((double)n)/9)/SQRT2; | |
167 ik = wint(1,NULL,0,WGAUS); | |
168 | |
169 td = 0; | |
170 for (i=0; i<n; i++) | |
171 for (j=i; j<n; j++) | |
172 { z = (x[i]-x[j])/b; | |
173 td += (2-(i==j))*Wconv6(z,WGAUS)/(ik*ik); | |
174 } | |
175 | |
176 td = -td/(n*(n-1)); | |
177 j = 2.0; | |
178 c1 = Wconv4(0.0,WGAUS); | |
179 c2 = wint(1,&j,1,WGAUS); | |
180 c3 = Wconv(0.0,WGAUS); /* (2*c1/(c2*c3))^(1/7)=1.357 */ | |
181 sa = compsda(x,a,n); | |
182 c = b*exp(log(c1*ik/(c2*c3*GFACT*GFACT*GFACT*GFACT)*sa/td)/7)*SQRT2; | |
183 return(c); | |
184 } | |
185 | |
186 void kdecri(x,h,res,c,k,ker,n) | |
187 double *x, h, *res, c; | |
188 int k, ker, n; | |
189 { int i, j; | |
190 double degfree, dfd, pen, s, r0, r1, d0, d1, ik, wij; | |
191 | |
192 if (h<=0) WARN(("kdecri, h = %6.4f",h)); | |
193 | |
194 res[0] = res[1] = 0.0; | |
195 ik = wint(1,NULL,0,ker); | |
196 switch(k) | |
197 { case 1: /* aic */ | |
198 pen = 2.0; | |
199 for (i=0; i<n; i++) | |
200 { r0 = d0 = 0.0; | |
201 for (j=0; j<n; j++) | |
202 { s = (x[i]-x[j])/h; | |
203 r0 += W(s,ker); | |
204 d0 += s*s*Wd(s,ker); | |
205 } | |
206 d0 = -(d0+r0)/(n*h*h*ik); /* d0 = d/dh fhat(xi) */ | |
207 r0 /= n*h*ik; /* r0 = fhat(xi) */ | |
208 res[0] += -2*log(r0)+pen*W(0.0,ker)/(n*h*ik*r0); | |
209 res[1] += -2*d0/r0-pen*W(0.0,ker)/(n*h*ik*r0)*(d0/r0+1.0/h); | |
210 } | |
211 return; | |
212 case 2: /* ocv */ | |
213 for (i=0; i<n; i++) | |
214 { r0 = 0.0; d0 = 0.0; | |
215 for (j=0; j<n; j++) if (i!=j) | |
216 { s = (x[i]-x[j])/h; | |
217 r0 += W(s,ker); | |
218 d0 += s*s*Wd(s,ker); | |
219 } | |
220 d0 = -(d0+r0)/((n-1)*h*h); | |
221 r0 = r0/((n-1)*h); | |
222 res[0] -= log(r0); | |
223 res[1] -= d0/r0; | |
224 } | |
225 return; | |
226 case 3: /* lscv */ | |
227 r0 = r1 = d0 = d1 = degfree = 0.0; | |
228 for (i=0; i<n; i++) | |
229 { dfd = 0.0; | |
230 for (j=0; j<n; j++) | |
231 { s = (x[i]-x[j])/h; | |
232 wij = W(s,ker); | |
233 dfd += wij; | |
234 /* | |
235 * r0 = \int fhat * fhat = sum_{i,j} W*W( (Xi-Xj)/h ) / n^2 h. | |
236 * d0 is it's derivative wrt h. | |
237 * | |
238 * r1 = 1/n sum( f_{-i}(X_i) ). | |
239 * d1 is it's derivative wrt h. | |
240 * | |
241 * degfree = sum_i ( W_0 / sum_j W( (Xi-Xj)/h ) ) is fitted d.f. | |
242 */ | |
243 r0 += Wconv(s,ker); | |
244 d0 += -s*s*Wconv1(s,ker); | |
245 if (i != j) | |
246 { r1 += wij; | |
247 d1 += -s*s*Wd(s,ker); | |
248 } | |
249 } | |
250 degfree += 1.0/dfd; | |
251 } | |
252 d1 -= r1; | |
253 d0 -= r0; | |
254 res[0] = r0/(n*n*h*ik*ik) - 2*r1/(n*(n-1)*h*ik); | |
255 res[1] = d0/(n*n*h*h*ik*ik) - 2*d1/(n*(n-1)*h*h*ik); | |
256 res[2] = degfree; | |
257 return; | |
258 case 4: /* bcv */ | |
259 r0 = d0 = 0.0; | |
260 for (i=0; i<n; i++) | |
261 for (j=i+1; j<n; j++) | |
262 { s = (x[i]-x[j])/h; | |
263 r0 += 2*Wconv4(s,ker); | |
264 d0 += 2*s*Wconv5(s,ker); | |
265 } | |
266 d0 = (-d0-r0)/(n*n*h*h*ik*ik); | |
267 r0 = r0/(n*n*h*ik*ik); | |
268 j = 2.0; | |
269 d1 = wint(1,&j,1,ker); | |
270 r1 = Wconv(0.0,ker); | |
271 res[0] = (d1*d1*r0/4+r1/(n*h))/(ik*ik); | |
272 res[1] = (d1*d1*d0/4-r1/(n*h*h))/(ik*ik); | |
273 return; | |
274 case 5: /* sjpi */ | |
275 s = c*exp(5*log(h)/7)/SQRT2; | |
276 d0 = compsda(x,s,n); | |
277 res[0] = d0; /* this is S(alpha) in SJ */ | |
278 res[1] = exp(log(Wikk(WGAUS,0)/(d0*n))/5)-h; | |
279 return; | |
280 case 6: /* gas-k-k */ | |
281 s = exp(log(1.0*n)/10)*h; | |
282 d0 = compsda(x,s,n); | |
283 res[0] = d0; | |
284 res[1] = exp(log(Wikk(WGAUS,0)/(d0*n))/5)-h; | |
285 return; | |
286 } | |
287 LERR(("kdecri: what???")); | |
288 return; | |
289 } | |
290 | |
291 double esolve(x,j,h0,h1,k,c,ker,n) | |
292 double *x, h0, h1, c; | |
293 int j, k, ker, n; | |
294 { double h[7], d[7], r[7], res[4], min, minh, fact; | |
295 int i, nc; | |
296 min = 1.0e30; minh = 0.0; | |
297 fact = 1.00001; | |
298 h[6] = h0; kdecri(x,h[6],res,c,j,ker,n); | |
299 r[6] = res[0]; d[6] = res[1]; | |
300 if (lf_error) return(0.0); | |
301 nc = 0; | |
302 for (i=0; i<k; i++) | |
303 { h[5] = h[6]; r[5] = r[6]; d[5] = d[6]; | |
304 h[6] = h0*exp((i+1)*log(h1/h0)/k); | |
305 kdecri(x,h[6],res,c,j,ker,n); | |
306 r[6] = res[0]; d[6] = res[1]; | |
307 if (lf_error) return(0.0); | |
308 if (d[5]*d[6]<0) | |
309 { h[2] = h[0] = h[5]; d[2] = d[0] = d[5]; r[2] = r[0] = r[5]; | |
310 h[3] = h[1] = h[6]; d[3] = d[1] = d[6]; r[3] = r[1] = r[6]; | |
311 while ((h[3]>fact*h[2])|(h[2]>fact*h[3])) | |
312 { h[4] = h[3]-d[3]*(h[3]-h[2])/(d[3]-d[2]); | |
313 if ((h[4]<h[0]) | (h[4]>h[1])) h[4] = (h[0]+h[1])/2; | |
314 kdecri(x,h[4],res,c,j,ker,n); | |
315 r[4] = res[0]; d[4] = res[1]; | |
316 if (lf_error) return(0.0); | |
317 h[2] = h[3]; h[3] = h[4]; | |
318 d[2] = d[3]; d[3] = d[4]; | |
319 r[2] = r[3]; r[3] = r[4]; | |
320 if (d[4]*d[0]>0) { h[0] = h[4]; d[0] = d[4]; r[0] = r[4]; } | |
321 else { h[1] = h[4]; d[1] = d[4]; r[1] = r[4]; } | |
322 } | |
323 if (j>=4) return(h[4]); /* first min for BCV etc */ | |
324 if (r[4]<=min) { min = r[4]; minh = h[4]; } | |
325 nc++; | |
326 } | |
327 } | |
328 if (nc==0) minh = (r[5]<r[6]) ? h0 : h1; | |
329 return(minh); | |
330 } | |
331 | |
332 void kdeselect(band,x,ind,h0,h1,meth,nm,ker,n) | |
333 double h0, h1, *band, *x; | |
334 int *ind, nm, ker, n, *meth; | |
335 { double scale, c; | |
336 int i, k; | |
337 k = n/4; | |
338 for (i=0; i<n; i++) ind[i] = i; | |
339 scale = kordstat(x,n+1-k,n,ind) - kordstat(x,k,n,ind); | |
340 c = widthsj(x,scale,n); | |
341 for (i=0; i<nm; i++) | |
342 band[i] = esolve(x,meth[i],h0,h1,10,c,ker,n); | |
343 } | |
344 /* | |
345 * Copyright 1996-2006 Catherine Loader. | |
346 */ | |
347 /* | |
348 * The function dens_integrate(lf,des,z) is used to integrate a density | |
349 * estimate (z=1) or the density squared (z=2). This is used to renormalize | |
350 * the estimate (function dens_renorm) or in the computation of LSCV | |
351 * (in modlscv.c). The implementation is presently for d=1. | |
352 * | |
353 * The computation orders the fit points selected by locfit, and | |
354 * integrates analytically over each interval. For the log-link, | |
355 * the interpolant used is peicewise quadratic (with one knot in | |
356 * the middle of each interval); this differs from the cubic interpolant | |
357 * used elsewhere in Locfit. | |
358 * | |
359 * TODO: allow for xlim. What can be done simply in >=2 dimensions? | |
360 */ | |
361 | |
362 #include "lfev.h" | |
363 | |
364 /* | |
365 * Finds the order of observations in the array x, and | |
366 * stores in integer array ind. | |
367 * At input, lset l=0 and r=length(x)-1. | |
368 * At output, x[ind[0]] <= x[ind[1]] <= ... | |
369 */ | |
370 void lforder(ind,x,l,r) | |
371 int *ind, l, r; | |
372 double *x; | |
373 { double piv; | |
374 int i, i0, i1; | |
375 piv = (x[ind[l]]+x[ind[r]])/2; | |
376 i0 = l; i1 = r; | |
377 while (i0<=i1) | |
378 { while ((i0<=i1) && (x[ind[i0]]<=piv)) i0++; | |
379 while ((i0<=i1) && (x[ind[i1]]>piv)) i1--; | |
380 if (i0<i1) | |
381 { ISWAP(ind[i0],ind[i1]); | |
382 i0++; i1--; | |
383 } | |
384 } | |
385 /* now, x[ind[l..i1]] <= piv < x[ind[i0..r]]. | |
386 put the ties in the middle */ | |
387 while ((i1>=l) && (x[ind[i1]]==piv)) i1--; | |
388 for (i=l; i<=i1; i++) | |
389 if (x[ind[i]]==piv) | |
390 { ISWAP(ind[i],ind[i1]); | |
391 while (x[ind[i1]]==piv) i1--; | |
392 } | |
393 | |
394 if (l<i1) lforder(ind,x,l,i1); | |
395 if (i0<r) lforder(ind,x,i0,r); | |
396 } | |
397 | |
398 /* | |
399 * estdiv integrates the density between fit points x0 and x1. | |
400 * f0, f1 are function values, d0, d1 are derivatives. | |
401 */ | |
402 double estdiv(x0,x1,f0,f1,d0,d1,lin) | |
403 double x0, x1, f0, f1, d0, d1; | |
404 int lin; | |
405 { double cf[4], I[2], dlt, e0, e1; | |
406 | |
407 if (x0==x1) return(0.0); | |
408 | |
409 if (lin==LIDENT) | |
410 { | |
411 /* cf are integrals of hermite polynomials. | |
412 * Then adjust for x1-x0. | |
413 */ | |
414 cf[0] = cf[1] = 0.5; | |
415 cf[2] = 1.0/12.0; cf[3] = -cf[2]; | |
416 return( (cf[0]*f0+cf[1]*f1)*(x1-x0) | |
417 + (cf[2]*d0+cf[3]*d1)*(x1-x0)*(x1-x0) ); | |
418 } | |
419 | |
420 /* | |
421 * this is for LLOG | |
422 */ | |
423 | |
424 dlt = (x1-x0)/2; | |
425 cf[0] = f0; | |
426 cf[1] = d0; | |
427 cf[2] = ( 2*(f1-f0) - dlt*(d1+3*d0) )/(4*dlt*dlt); | |
428 recurint(0.0,dlt,cf,I,0,WRECT); | |
429 e0 = I[0]; | |
430 | |
431 cf[0] = f1; | |
432 cf[1] = -d1; | |
433 cf[2] = ( 2*(f0-f1) + dlt*(d0+3*d1) )/( 4*dlt*dlt ); | |
434 recurint(0.0,dlt,cf,I,0,WRECT); | |
435 e1 = I[0]; | |
436 | |
437 return(e0+e1); | |
438 } | |
439 | |
440 /* | |
441 * Evaluate the integral of the density estimate to the power z. | |
442 * This would be severely messed up, if I ever implement parcomp | |
443 * for densities. | |
444 */ | |
445 double dens_integrate(lf,des,z) | |
446 lfit *lf; | |
447 design *des; | |
448 int z; | |
449 { int has_deriv, i, i0, i1, nv, *ind; | |
450 double *xev, *fit, *deriv, sum, term; | |
451 double d0, d1, f0, f1; | |
452 fitpt *fp; | |
453 | |
454 fp = &lf->fp; | |
455 | |
456 if (fp->d >= 2) | |
457 { WARN(("dens_integrate requires d=1")); | |
458 return(0.0); | |
459 } | |
460 | |
461 has_deriv = (deg(&lf->sp) > 0); /* not right? */ | |
462 fit = fp->coef; | |
463 if (has_deriv) | |
464 deriv = &fit[fp->nvm]; | |
465 xev = evp(fp); | |
466 | |
467 /* | |
468 * order the vertices | |
469 */ | |
470 nv = fp->nv; | |
471 if (lf->lfd.n<nv) return(0.0); | |
472 ind = des->ind; | |
473 for (i=0; i<nv; i++) ind[i] = i; | |
474 lforder(ind,xev,0,nv-1); | |
475 sum = 0.0; | |
476 | |
477 /* | |
478 * Estimate the contribution of the boundaries. | |
479 * should really check flim here. | |
480 */ | |
481 i0 = ind[0]; i1 = ind[1]; | |
482 f1 = fit[i0]; | |
483 d1 = (has_deriv) ? deriv[i0] : | |
484 (fit[i1]-fit[i0])/(xev[i1]-xev[i0]); | |
485 if (d1 <= 0) WARN(("dens_integrate - ouch!")); | |
486 if (z==2) | |
487 { if (link(&lf->sp)==LLOG) | |
488 { f1 *= 2; d1 *= 2; } | |
489 else | |
490 { d1 = 2*d1*f1; f1 = f1*f1; } | |
491 } | |
492 term = (link(&lf->sp)==LIDENT) ? f1*f1/(2*d1) : exp(f1)/d1; | |
493 sum += term; | |
494 | |
495 i0 = ind[nv-2]; i1 = ind[nv-1]; | |
496 f0 = fit[i1]; | |
497 d0 = (has_deriv) ? deriv[i1] : | |
498 (fit[i1]-fit[i0])/(xev[i1]-xev[i0]); | |
499 if (d0 >= 0) WARN(("dens_integrate - ouch!")); | |
500 if (z==2) | |
501 { if (link(&lf->sp)==LLOG) | |
502 { f0 *= 2; d0 *= 2; } | |
503 else | |
504 { d0 = 2*d0*f0; f0 = f0*f0; } | |
505 } | |
506 term = (link(&lf->sp)==LIDENT) ? -f0*f0/(2*d0) : exp(f0)/d0; | |
507 sum += term; | |
508 | |
509 for (i=1; i<nv; i++) | |
510 { i0 = ind[i-1]; i1 = ind[i]; | |
511 f0 = fit[i0]; f1 = fit[i1]; | |
512 d0 = (has_deriv) ? deriv[i0] : | |
513 (f1-f0)/(xev[i1]-xev[i0]); | |
514 d1 = (has_deriv) ? deriv[i1] : d0; | |
515 if (z==2) | |
516 { if (link(&lf->sp)==LLOG) | |
517 { f0 *= 2; f1 *= 2; d0 *= 2; d1 *= 2; } | |
518 else | |
519 { d0 *= 2*f0; d1 *= 2*f1; f0 = f0*f0; f1 = f1*f1; } | |
520 } | |
521 term = estdiv(xev[i0],xev[i1],f0,f1,d0,d1,link(&lf->sp)); | |
522 sum += term; | |
523 } | |
524 | |
525 return(sum); | |
526 } | |
527 | |
528 void dens_renorm(lf,des) | |
529 lfit *lf; | |
530 design *des; | |
531 { int i; | |
532 double sum; | |
533 sum = dens_integrate(lf,des,1); | |
534 if (sum==0.0) return; | |
535 sum = log(sum); | |
536 for (i=0; i<lf->fp.nv; i++) lf->fp.coef[i] -= sum; | |
537 } | |
538 /* | |
539 * Copyright 1996-2006 Catherine Loader. | |
540 */ | |
541 /* | |
542 * This file contains functions for constructing and | |
543 * interpolating the adaptive tree structure. This is | |
544 * the default evaluation structure used by Locfit. | |
545 */ | |
546 | |
547 #include "lfev.h" | |
548 | |
549 /* | |
550 Guess the number of fitting points. | |
551 Needs improving! | |
552 */ | |
553 void atree_guessnv(evs,nvm,ncm,vc,d,alp) | |
554 evstruc *evs; | |
555 double alp; | |
556 int *nvm, *ncm, *vc, d; | |
557 { double a0, cu, ifl; | |
558 int i, nv, nc; | |
559 | |
560 *ncm = 1<<30; *nvm = 1<<30; | |
561 *vc = 1 << d; | |
562 | |
563 if (alp>0) | |
564 { a0 = (alp > 1) ? 1 : 1/alp; | |
565 if (cut(evs)<0.01) | |
566 { WARN(("guessnv: cut too small.")); | |
567 cut(evs) = 0.01; | |
568 } | |
569 cu = 1; | |
570 for (i=0; i<d; i++) cu *= MIN(1.0,cut(evs)); | |
571 nv = (int)((5*a0/cu)**vc); /* this allows 10*a0/cu splits */ | |
572 nc = (int)(10*a0/cu+1); /* and 10*a0/cu cells */ | |
573 if (nv<*nvm) *nvm = nv; | |
574 if (nc<*ncm) *ncm = nc; | |
575 } | |
576 | |
577 if (*nvm == 1<<30) /* by default, allow 100 splits */ | |
578 { *nvm = 102**vc; | |
579 *ncm = 201; | |
580 } | |
581 | |
582 /* inflation based on mk */ | |
583 ifl = mk(evs)/100.0; | |
584 *nvm = *vc+(int)(ifl**nvm); | |
585 *ncm = (int)(ifl**ncm); | |
586 | |
587 } | |
588 | |
589 /* | |
590 Determine whether a cell in the tree needs splitting. | |
591 If so, return the split variable (0..d-1). | |
592 Otherwise, return -1. | |
593 */ | |
594 int atree_split(lf,ce,le,ll,ur) | |
595 lfit *lf; | |
596 int *ce; | |
597 double *le, *ll, *ur; | |
598 { int d, vc, i, is; | |
599 double h, hmin, score[MXDIM]; | |
600 d = lf->fp.d; vc = 1<<d; | |
601 | |
602 hmin = 0.0; | |
603 for (i=0; i<vc; i++) | |
604 { h = lf->fp.h[ce[i]]; | |
605 if ((h>0) && ((hmin==0)|(h<hmin))) hmin = h; | |
606 } | |
607 | |
608 is = 0; | |
609 for (i=0; i<d; i++) | |
610 { le[i] = (ur[i]-ll[i])/lf->lfd.sca[i]; | |
611 if ((lf->lfd.sty[i]==STCPAR) || (hmin==0)) | |
612 score[i] = 2*(ur[i]-ll[i])/(lf->evs.fl[i+d]-lf->evs.fl[i]); | |
613 else | |
614 score[i] = le[i]/hmin; | |
615 if (score[i]>score[is]) is = i; | |
616 } | |
617 if (cut(&lf->evs)<score[is]) return(is); | |
618 return(-1); | |
619 } | |
620 | |
621 /* | |
622 recursively grow the tree structure, begining with the parent cell. | |
623 */ | |
624 void atree_grow(des,lf,ce,ct,term,ll,ur) | |
625 design *des; | |
626 lfit *lf; | |
627 int *ce, *ct, *term; | |
628 double *ll, *ur; | |
629 { int nce[1<<MXDIM]; | |
630 int i, i0, i1, d, vc, pv, tk, ns; | |
631 double le[MXDIM], z; | |
632 d = lf->fp.d; vc = 1<<d; | |
633 | |
634 /* does this cell need splitting? | |
635 If not, wrap up and return. | |
636 */ | |
637 ns = atree_split(lf,ce,le,ll,ur); | |
638 if (ns==-1) | |
639 { if (ct != NULL) /* reconstructing terminal cells */ | |
640 { for (i=0; i<vc; i++) term[*ct*vc+i] = ce[i]; | |
641 (*ct)++; | |
642 } | |
643 return; | |
644 } | |
645 | |
646 /* split the cell at the midpoint on side ns */ | |
647 tk = 1<<ns; | |
648 for (i=0; i<vc; i++) | |
649 { if ((i&tk)==0) nce[i] = ce[i]; | |
650 else | |
651 { i0 = ce[i]; | |
652 i1 = ce[i-tk]; | |
653 pv = (lf->lfd.sty[i]!=STCPAR) && | |
654 (le[ns] < (cut(&lf->evs)*MIN(lf->fp.h[i0],lf->fp.h[i1]))); | |
655 nce[i] = newsplit(des,lf,i0,i1,pv); | |
656 if (lf_error) return; | |
657 } | |
658 } | |
659 z = ur[ns]; ur[ns] = (z+ll[ns])/2; | |
660 atree_grow(des,lf,nce,ct,term,ll,ur); | |
661 if (lf_error) return; | |
662 ur[ns] = z; | |
663 for (i=0; i<vc; i++) | |
664 nce[i] = ((i&tk)== 0) ? nce[i+tk] : ce[i]; | |
665 z = ll[ns]; ll[ns] = (z+ur[ns])/2; | |
666 atree_grow(des,lf,nce,ct,term,ll,ur); | |
667 if (lf_error) return; | |
668 ll[ns] = z; | |
669 } | |
670 | |
671 void atree_start(des,lf) | |
672 design *des; | |
673 lfit *lf; | |
674 { int d, i, j, k, vc, ncm, nvm; | |
675 double ll[MXDIM], ur[MXDIM]; | |
676 | |
677 if (lf_debug>1) mut_printf(" In atree_start\n"); | |
678 d = lf->fp.d; | |
679 atree_guessnv(&lf->evs,&nvm,&ncm,&vc,d,nn(&lf->sp)); | |
680 if (lf_debug>2) mut_printf(" atree_start: nvm %d ncm %d\n",nvm,ncm); | |
681 trchck(lf,nvm,ncm,vc); | |
682 | |
683 /* Set the lower left, upper right limits. */ | |
684 for (j=0; j<d; j++) | |
685 { ll[j] = lf->evs.fl[j]; | |
686 ur[j] = lf->evs.fl[j+d]; | |
687 } | |
688 | |
689 /* Set the initial cell; fit at the vertices. */ | |
690 for (i=0; i<vc; i++) | |
691 { j = i; | |
692 for (k=0; k<d; ++k) | |
693 { evptx(&lf->fp,i,k) = (j%2) ? ur[k] : ll[k]; | |
694 j >>= 1; | |
695 } | |
696 lf->evs.ce[i] = i; | |
697 PROC_VERTEX(des,lf,i); | |
698 if (lf_error) return; | |
699 lf->evs.s[i] = 0; | |
700 } | |
701 lf->fp.nv = vc; | |
702 | |
703 /* build the tree */ | |
704 atree_grow(des,lf,lf->evs.ce,NULL,NULL,ll,ur); | |
705 lf->evs.nce = 1; | |
706 } | |
707 | |
708 double atree_int(lf,x,what) | |
709 lfit *lf; | |
710 double *x; | |
711 int what; | |
712 { double vv[64][64], *ll, *ur, h, xx[MXDIM]; | |
713 int lo, tk, ns, nv, nc, d, i, vc; | |
714 int ce[64]; | |
715 fitpt *fp; | |
716 evstruc *evs; | |
717 | |
718 fp = &lf->fp; | |
719 evs= &lf->evs; | |
720 d = fp->d; | |
721 vc = 1<<d; | |
722 | |
723 for (i=0; i<vc; i++) | |
724 { setzero(vv[i],vc); | |
725 nc = exvval(fp,vv[i],i,d,what,1); | |
726 ce[i] = evs->ce[i]; | |
727 } | |
728 ns = 0; | |
729 while(ns!=-1) | |
730 { ll = evpt(fp,ce[0]); ur = evpt(fp,ce[vc-1]); | |
731 ns = atree_split(lf,ce,xx,ll,ur); | |
732 if (ns!=-1) | |
733 { tk = 1<<ns; | |
734 h = ur[ns]-ll[ns]; | |
735 lo = (2*(x[ns]-ll[ns])) < h; | |
736 for (i=0; i<vc; i++) if ((tk&i)==0) | |
737 { nv = findpt(fp,evs,(int)ce[i],(int)ce[i+tk]); | |
738 if (nv==-1) LERR(("Descend tree problem")); | |
739 if (lf_error) return(0.0); | |
740 if (lo) | |
741 { ce[i+tk] = nv; | |
742 if (evs->s[nv]) exvvalpv(vv[i+tk],vv[i],vv[i+tk],d,ns,h,nc); | |
743 else exvval(fp,vv[i+tk],nv,d,what,1); | |
744 } | |
745 else | |
746 { ce[i] = nv; | |
747 if (evs->s[nv]) exvvalpv(vv[i],vv[i],vv[i+tk],d,ns,h,nc); | |
748 else exvval(fp,vv[i],nv,d,what,1); | |
749 } } | |
750 } } | |
751 ll = evpt(fp,ce[0]); ur = evpt(fp,ce[vc-1]); | |
752 return(rectcell_interp(x,vv,ll,ur,d,nc)); | |
753 } | |
754 /* | |
755 * Copyright 1996-2006 Catherine Loader. | |
756 */ | |
757 #include "lfev.h" | |
758 | |
759 double linear_interp(h,d,f0,f1) | |
760 double h, d, f0, f1; | |
761 { if (d==0) return(f0); | |
762 return( ( (d-h)*f0 + h*f1 ) / d ); | |
763 } | |
764 | |
765 void hermite2(x,z,phi) | |
766 double x, z, *phi; | |
767 { double h; | |
768 if (z==0) | |
769 { phi[0] = 1.0; phi[1] = phi[2] = phi[3] = 0.0; | |
770 return; | |
771 } | |
772 h = x/z; | |
773 if (h<0) | |
774 { phi[0] = 1; phi[1] = 0; | |
775 phi[2] = h; phi[3] = 0; | |
776 return; | |
777 } | |
778 if (h>1) | |
779 { phi[0] = 0; phi[1] = 1; | |
780 phi[2] = 0; phi[3] = h-1; | |
781 return; | |
782 } | |
783 phi[1] = h*h*(3-2*h); | |
784 phi[0] = 1-phi[1]; | |
785 phi[2] = h*(1-h)*(1-h); | |
786 phi[3] = h*h*(h - 1); | |
787 } | |
788 | |
789 double cubic_interp(h,f0,f1,d0,d1) | |
790 double h, f0, f1, d0, d1; | |
791 { double phi[4]; | |
792 hermite2(h,1.0,phi); | |
793 return(phi[0]*f0+phi[1]*f1+phi[2]*d0+phi[3]*d1); | |
794 } | |
795 | |
796 double cubintd(h,f0,f1,d0,d1) | |
797 double h, f0, f1, d0, d1; | |
798 { double phi[4]; | |
799 phi[1] = 6*h*(1-h); | |
800 phi[0] = -phi[1]; | |
801 phi[2] = (1-h)*(1-3*h); | |
802 phi[3] = h*(3*h-2); | |
803 return(phi[0]*f0+phi[1]*f1+phi[2]*d0+phi[3]*d1); | |
804 } | |
805 | |
806 /* | |
807 interpolate over a rectangular cell. | |
808 x = interpolation point. | |
809 vv = array of vertex values. | |
810 ll = lower left corner. | |
811 ur = upper right corner. | |
812 d = dimension. | |
813 nc = no of coefficients. | |
814 */ | |
815 double rectcell_interp(x,vv,ll,ur,d,nc) | |
816 double *x, vv[64][64], *ll, *ur; | |
817 int d, nc; | |
818 { double phi[4]; | |
819 int i, j, k, tk; | |
820 | |
821 tk = 1<<d; | |
822 for (i=0; i<tk; i++) if (vv[i][0]==NOSLN) return(NOSLN); | |
823 | |
824 /* no derivatives - use multilinear interpolation */ | |
825 if (nc==1) | |
826 { for (i=d-1; i>=0; i--) | |
827 { tk = 1<<i; | |
828 for (j=0; j<tk; j++) | |
829 vv[j][0] = linear_interp(x[i]-ll[i],ur[i]-ll[i],vv[j][0],vv[j+tk][0]); | |
830 } | |
831 return(vv[0][0]); | |
832 } | |
833 | |
834 /* with derivatives -- use cubic */ | |
835 if (nc==d+1) | |
836 { for (i=d-1; i>=0; i--) | |
837 { hermite2(x[i]-ll[i],ur[i]-ll[i],phi); | |
838 tk = 1<<i; | |
839 phi[2] *= ur[i]-ll[i]; | |
840 phi[3] *= ur[i]-ll[i]; | |
841 for (j=0; j<tk; j++) | |
842 { vv[j][0] = phi[0]*vv[j][0] + phi[1]*vv[j+tk][0] | |
843 + phi[2]*vv[j][i+1] + phi[3]*vv[j+tk][i+1]; | |
844 for (k=1; k<=i; k++) | |
845 vv[j][k] = phi[0]*vv[j][k] + phi[1]*vv[j+tk][k]; | |
846 } | |
847 } | |
848 return(vv[0][0]); | |
849 } | |
850 | |
851 /* with all coefs -- use multicubic */ | |
852 for (i=d-1; i>=0; i--) | |
853 { hermite2(x[i]-ll[i],ur[i]-ll[i],phi); | |
854 tk = 1<<i; | |
855 phi[2] *= ur[i]-ll[i]; | |
856 phi[3] *= ur[i]-ll[i]; | |
857 for (j=0; j<tk; j++) | |
858 for (k=0; k<tk; k++) | |
859 vv[j][k] = phi[0]*vv[j][k] + phi[1]*vv[j+tk][k] | |
860 + phi[2]*vv[j][k+tk] + phi[3]*vv[j+tk][k+tk]; | |
861 } | |
862 return(vv[0][0]); | |
863 } | |
864 | |
865 int exvval(fp,vv,nv,d,what,z) | |
866 fitpt *fp; | |
867 double *vv; | |
868 int nv, d, z, what; | |
869 { int i, k; | |
870 double *values; | |
871 | |
872 k = (z) ? 1<<d : d+1; | |
873 for (i=1; i<k; i++) vv[i] = 0.0; | |
874 switch(what) | |
875 { case PCOEF: | |
876 values = fp->coef; | |
877 break; | |
878 case PVARI: | |
879 case PNLX: | |
880 values = fp->nlx; | |
881 break; | |
882 case PT0: | |
883 values = fp->t0; | |
884 break; | |
885 case PBAND: | |
886 vv[0] = fp->h[nv]; | |
887 return(1); | |
888 case PDEGR: | |
889 vv[0] = fp->deg[nv]; | |
890 return(1); | |
891 case PLIK: | |
892 vv[0] = fp->lik[nv]; | |
893 return(1); | |
894 case PRDF: | |
895 vv[0] = fp->lik[2*fp->nvm+nv]; | |
896 return(1); | |
897 default: | |
898 LERR(("Invalid what in exvval")); | |
899 return(0); | |
900 } | |
901 vv[0] = values[nv]; | |
902 if (!fp->hasd) return(1); | |
903 if (z) | |
904 { for (i=0; i<d; i++) vv[1<<i] = values[(i+1)*fp->nvm+nv]; | |
905 return(1<<d); | |
906 } | |
907 else | |
908 { for (i=1; i<=d; i++) vv[i] = values[i*fp->nvm+nv]; | |
909 return(d+1); | |
910 } | |
911 } | |
912 | |
913 void exvvalpv(vv,vl,vr,d,k,dl,nc) | |
914 double *vv, *vl, *vr, dl; | |
915 int d, k, nc; | |
916 { int i, tk, td; | |
917 double f0, f1; | |
918 if (nc==1) | |
919 { vv[0] = (vl[0]+vr[0])/2; | |
920 return; | |
921 } | |
922 tk = 1<<k; | |
923 td = 1<<d; | |
924 for (i=0; i<td; i++) if ((i&tk)==0) | |
925 { f0 = (vl[i]+vr[i])/2 + dl*(vl[i+tk]-vr[i+tk])/8; | |
926 f1 = 1.5*(vr[i]-vl[i])/dl - (vl[i+tk]+vr[i+tk])/4; | |
927 vv[i] = f0; | |
928 vv[i+tk] = f1; | |
929 } | |
930 } | |
931 | |
932 double grid_int(fp,evs,x,what) | |
933 fitpt *fp; | |
934 evstruc *evs; | |
935 double *x; | |
936 int what; | |
937 { int d, i, j, jj, nc, sk, v[MXDIM], vc, z0, nce[1<<MXDIM], *mg; | |
938 double *ll, *ur, vv[64][64], z; | |
939 | |
940 d = fp->d; | |
941 ll = evpt(fp,0); ur = evpt(fp,fp->nv-1); | |
942 mg = mg(evs); | |
943 | |
944 z0 = 0; vc = 1<<d; | |
945 for (j=d-1; j>=0; j--) | |
946 { v[j] = (int)((mg[j]-1)*(x[j]-ll[j])/(ur[j]-ll[j])); | |
947 if (v[j]<0) v[j]=0; | |
948 if (v[j]>=mg[j]-1) v[j] = mg[j]-2; | |
949 z0 = z0*mg[j]+v[j]; | |
950 } | |
951 nce[0] = z0; nce[1] = z0+1; sk = jj = 1; | |
952 for (i=1; i<d; i++) | |
953 { sk *= mg[i-1]; | |
954 jj<<=1; | |
955 for (j=0; j<jj; j++) | |
956 nce[j+jj] = nce[j]+sk; | |
957 } | |
958 for (i=0; i<vc; i++) | |
959 nc = exvval(fp,vv[i],nce[i],d,what,1); | |
960 ll = evpt(fp,nce[0]); | |
961 ur = evpt(fp,nce[vc-1]); | |
962 z = rectcell_interp(x,vv,ll,ur,d,nc); | |
963 return(z); | |
964 } | |
965 | |
966 double fitp_int(fp,x,what,i) | |
967 fitpt *fp; | |
968 double *x; | |
969 int what, i; | |
970 { double vv[1+MXDIM]; | |
971 exvval(fp,vv,i,fp->d,what,0); | |
972 return(vv[0]); | |
973 } | |
974 | |
975 double xbar_int(fp,x,what) | |
976 fitpt *fp; | |
977 double *x; | |
978 int what; | |
979 { int i, nc; | |
980 double vv[1+MXDIM], f; | |
981 nc = exvval(fp,vv,0,fp->d,what,0); | |
982 f = vv[0]; | |
983 if (nc>1) | |
984 for (i=0; i<fp->d; i++) | |
985 f += vv[i+1]*(x[i]-evptx(fp,0,i)); | |
986 return(f); | |
987 } | |
988 | |
989 double dointpoint(lf,x,what,ev,j) | |
990 lfit *lf; | |
991 double *x; | |
992 int what, ev, j; | |
993 { double xf, f, link[LLEN]; | |
994 int i, rt; | |
995 fitpt *fp; | |
996 evstruc *evs; | |
997 | |
998 fp = &lf->fp; evs = &lf->evs; | |
999 for (i=0; i<fp->d; i++) if (lf->lfd.sty[i]==STANGL) | |
1000 { xf = floor(x[i]/(2*PI*lf->lfd.sca[i])); | |
1001 x[i] -= xf*2*PI*lf->lfd.sca[i]; | |
1002 } | |
1003 if (what > 64) | |
1004 { rt = what-64; | |
1005 what = PCOEF; | |
1006 } | |
1007 else rt = 0; | |
1008 | |
1009 switch(ev) | |
1010 { case EGRID: f = grid_int(fp,evs,x,what); break; | |
1011 case EKDTR: f = kdtre_int(fp,evs,x,what); break; | |
1012 case ETREE: f = atree_int(lf,x,what); break; | |
1013 case EPHULL: f = triang_int(lf,x,what); break; | |
1014 case EFITP: f = fitp_int(fp,x,what,j); break; | |
1015 case EXBAR: f = xbar_int(fp,x,what); break; | |
1016 case ENONE: f = 0; break; | |
1017 case ESPHR: f = sphere_int(lf,x,what); break; | |
1018 default: LERR(("dointpoint: cannot interpolate structure %d",ev)); | |
1019 } | |
1020 if (((what==PT0)|(what==PNLX)) && (f<0)) f = 0.0; | |
1021 f += addparcomp(lf,x,what); | |
1022 | |
1023 if (rt>0) | |
1024 { | |
1025 stdlinks(link,&lf->lfd,&lf->sp,j,f,rsc(fp)); | |
1026 f = resid(resp(&lf->lfd,j),prwt(&lf->lfd,j),f,fam(&lf->sp),rt,link); | |
1027 } | |
1028 | |
1029 return(f); | |
1030 } | |
1031 /* | |
1032 * Copyright 1996-2006 Catherine Loader. | |
1033 */ | |
1034 /* | |
1035 * Routines for building and interpolating the kd tree. | |
1036 * Initially, this started from the loess code. | |
1037 * | |
1038 * Todo: EKDCE isn't working. | |
1039 */ | |
1040 | |
1041 #include "lfev.h" | |
1042 | |
1043 void newcell(); | |
1044 static int nterm; | |
1045 | |
1046 void kdtre_guessnv(evs,nvm,ncm,vc,n,d,alp) | |
1047 evstruc *evs; | |
1048 double alp; | |
1049 int *nvm, *ncm, *vc, n, d; | |
1050 { int k; | |
1051 if (ev(evs) == EKDTR) | |
1052 { nterm = (int)(cut(evs)/4 * n * MIN(alp,1.0) ); | |
1053 k = 2*n/nterm; | |
1054 *vc = 1<<d; | |
1055 *ncm = 2*k+1; | |
1056 *nvm = (k+2)**vc/2; | |
1057 return; | |
1058 } | |
1059 if (ev(evs) == EKDCE) | |
1060 { nterm = (int)(n * alp); | |
1061 *vc = 1; | |
1062 *nvm = 1+(int)(2*n/nterm); | |
1063 *ncm = 2**nvm+1; | |
1064 return; | |
1065 } | |
1066 *nvm = *ncm = *vc = 0; | |
1067 return; | |
1068 } | |
1069 | |
1070 /* | |
1071 Split x[pi[l..r]] into two equal sized sets. | |
1072 | |
1073 Let m=(l+r)/2. | |
1074 At return, | |
1075 x[pi[l..m]] < x[pi[m+1..r]]. | |
1076 Assuming no ties: | |
1077 If l+r is odd, the sets have the same size. | |
1078 If l+r is even, the low set is larger by 1. | |
1079 If there are ties, all ties go in the low set. | |
1080 */ | |
1081 int ksmall(l, r, m, x, pi) | |
1082 int l, r, m, *pi; | |
1083 double *x; | |
1084 { | |
1085 int il, ir, jl, jr; | |
1086 double t; | |
1087 | |
1088 | |
1089 while(l<r) | |
1090 { t = x[pi[m]]; | |
1091 | |
1092 /* | |
1093 permute the observations so that | |
1094 x[pi[l..il]] < t <= x[pi[ir..r]]. | |
1095 */ | |
1096 ir = l; il = r; | |
1097 while (ir<il) | |
1098 { while ((ir<=r) && (x[pi[ir]] < t)) ir++; | |
1099 while ((il>=l) && (x[pi[il]]>= t)) il--; | |
1100 if (ir<il) ISWAP(pi[ir],pi[il]); | |
1101 } | |
1102 | |
1103 /* | |
1104 move = t to the middle: | |
1105 x[pi[l..il]] < t | |
1106 x[pi[jl..jr]] = t | |
1107 x[pi[ir..r]] > t | |
1108 */ | |
1109 jl = ir; jr = r; | |
1110 while (ir<jr) | |
1111 { while ((ir<=r) && (x[pi[ir]]== t)) ir++; | |
1112 while ((jr>=jl) && (x[pi[jr]] > t)) jr--; | |
1113 if (ir<jr) ISWAP(pi[ir],pi[jr]); | |
1114 } | |
1115 | |
1116 /* | |
1117 we're done if m is in the middle, jl <= m <= jr. | |
1118 */ | |
1119 if ((jl<=m) & (jr>=m)) return(jr); | |
1120 | |
1121 /* | |
1122 update l or r. | |
1123 */ | |
1124 if (m>=ir) l = ir; | |
1125 if (m<=il) r = il; | |
1126 } | |
1127 if (l==r) return(l); | |
1128 LERR(("ksmall failure")); | |
1129 return(0); | |
1130 } | |
1131 | |
1132 int terminal(lf,p,pi,fc,d,m,split_val) | |
1133 lfit *lf; | |
1134 int p, d, fc, *m, *pi; | |
1135 double *split_val; | |
1136 { int i, k, lo, hi, split_var; | |
1137 double max, min, score, max_score, t; | |
1138 | |
1139 /* | |
1140 if there are fewer than fc points in the cell, this cell | |
1141 is terminal. | |
1142 */ | |
1143 lo = lf->evs.lo[p]; hi = lf->evs.hi[p]; | |
1144 if (hi-lo < fc) return(-1); | |
1145 | |
1146 /* determine the split variable */ | |
1147 max_score = 0.0; split_var = 0; | |
1148 for (k=0; k<d; k++) | |
1149 { max = min = datum(&lf->lfd, k, pi[lo]); | |
1150 for (i=lo+1; i<=hi; i++) | |
1151 { t = datum(&lf->lfd,k,pi[i]); | |
1152 if (t<min) min = t; | |
1153 if (t>max) max = t; | |
1154 } | |
1155 score = (max-min) / lf->lfd.sca[k]; | |
1156 if (score > max_score) | |
1157 { max_score = score; | |
1158 split_var = k; | |
1159 } | |
1160 } | |
1161 if (max_score==0) /* all points in the cell are equal */ | |
1162 return(-1); | |
1163 | |
1164 *m = ksmall(lo,hi,(lo+hi)/2, dvari(&lf->lfd,split_var), pi); | |
1165 *split_val = datum(&lf->lfd, split_var, pi[*m]); | |
1166 | |
1167 if (*m==hi) /* all observations go lo */ | |
1168 return(-1); | |
1169 return(split_var); | |
1170 } | |
1171 | |
1172 void kdtre_start(des,lf) | |
1173 design *des; | |
1174 lfit *lf; | |
1175 { | |
1176 int i, j, vc, d, nc, nv, ncm, nvm, k, m, n, p, *pi; | |
1177 double sv; | |
1178 d = lf->lfd.d; n = lf->lfd.n; pi = des->ind; | |
1179 kdtre_guessnv(&lf->evs,&nvm,&ncm,&vc,n,d,nn(&lf->sp)); | |
1180 trchck(lf,nvm,ncm,vc); | |
1181 | |
1182 nv = 0; | |
1183 if (ev(&lf->evs) != EKDCE) | |
1184 { for (i=0; i<vc; i++) | |
1185 { j = i; | |
1186 for (k=0; k<d; ++k) | |
1187 { evptx(&lf->fp,i,k) = lf->evs.fl[d*(j%2)+k]; | |
1188 j >>= 1; | |
1189 } | |
1190 } | |
1191 nv = vc; | |
1192 for (j=0; j<vc; j++) lf->evs.ce[j] = j; | |
1193 } | |
1194 | |
1195 for (i=0; i<n; i++) pi[i] = i; | |
1196 p = 0; nc = 1; | |
1197 lf->evs.lo[p] = 0; lf->evs.hi[p] = n-1; | |
1198 lf->evs.s[p] = -1; | |
1199 while (p<nc) | |
1200 { k = terminal(lf,p,pi,nterm,d,&m,&sv); | |
1201 if (k>=0) | |
1202 { | |
1203 if ((ncm<nc+2) | (2*nvm<2*nv+vc)) | |
1204 { WARN(("Insufficient space for full tree")); | |
1205 lf->evs.nce = nc; lf->fp.nv = nv; | |
1206 return; | |
1207 } | |
1208 | |
1209 /* new lo cell has obsn's lo[p]..m */ | |
1210 lf->evs.lo[nc] = lf->evs.lo[p]; | |
1211 lf->evs.hi[nc] = m; | |
1212 lf->evs.s[nc] = -1; | |
1213 | |
1214 /* new hi cell has obsn's m+1..hi[p] */ | |
1215 lf->evs.lo[nc+1] = m+1; | |
1216 lf->evs.hi[nc+1] = lf->evs.hi[p]; | |
1217 lf->evs.s[nc+1] = -1; | |
1218 | |
1219 /* cell p is split on variable k, value sv */ | |
1220 lf->evs.s[p] = k; | |
1221 lf->evs.sv[p] = sv; | |
1222 lf->evs.lo[p] = nc; lf->evs.hi[p] = nc+1; | |
1223 | |
1224 nc=nc+2; i = nv; | |
1225 | |
1226 /* now compute the new vertices. */ | |
1227 if (ev(&lf->evs) != EKDCE) | |
1228 newcell(&nv,vc,evp(&lf->fp), d, k, sv, | |
1229 &lf->evs.ce[p*vc], &lf->evs.ce[(nc-2)*vc], &lf->evs.ce[(nc-1)*vc]); | |
1230 | |
1231 } | |
1232 else if (ev(&lf->evs)==EKDCE) /* new vertex at cell center */ | |
1233 { sv = 0; | |
1234 for (i=0; i<d; i++) evptx(&lf->fp,nv,i) = 0; | |
1235 for (j=lf->evs.lo[p]; j<=lf->evs.hi[p]; j++) | |
1236 { sv += prwt(&lf->lfd,(int)pi[j]); | |
1237 for (i=0; i<d; i++) | |
1238 evptx(&lf->fp,nv,i) += datum(&lf->lfd,i,pi[j])*prwt(&lf->lfd,(int)pi[j]); | |
1239 } | |
1240 for (i=0; i<d; i++) evptx(&lf->fp,nv,i) /= sv; | |
1241 lf->lfd.n = lf->evs.hi[p] - lf->evs.lo[p] + 1; | |
1242 des->ind = &pi[lf->evs.lo[p]]; /* why? */ | |
1243 PROC_VERTEX(des,lf,nv); | |
1244 lf->lfd.n = n; des->ind = pi; | |
1245 nv++; | |
1246 } | |
1247 p++; | |
1248 } | |
1249 | |
1250 /* We've built the tree. Now do the fitting. */ | |
1251 if (ev(&lf->evs)==EKDTR) | |
1252 for (i=0; i<nv; i++) PROC_VERTEX(des,lf,i); | |
1253 | |
1254 lf->evs.nce = nc; lf->fp.nv = nv; | |
1255 return; | |
1256 } | |
1257 | |
1258 void newcell(nv,vc,xev, d, k, split_val, cpar, clef, crig) | |
1259 double *xev, split_val; | |
1260 int *cpar, *clef, *crig; | |
1261 int *nv, vc, d, k; | |
1262 { int i, ii, j, j2, tk, match; | |
1263 tk = 1<<k; | |
1264 for (i=0; i<vc; i++) | |
1265 { if ((i&tk) == 0) | |
1266 { for (j=0; j<d; j++) xev[*nv*d+j] = xev[d*cpar[i]+j]; | |
1267 xev[*nv*d+k] = split_val; | |
1268 match = 0; j = vc; /* no matches in first vc points */ | |
1269 while ((j<*nv) && (!match)) | |
1270 { j2 = 0; | |
1271 while ((j2<d) && (xev[*nv*d+j2] == xev[j*d+j2])) j2++; | |
1272 match = (j2==d); | |
1273 if (!match) j++; | |
1274 } | |
1275 ii = i+tk; | |
1276 clef[i] = cpar[i]; | |
1277 clef[ii]= crig[i] = j; | |
1278 crig[ii]= cpar[ii]; | |
1279 if (!match) (*nv)++; | |
1280 } | |
1281 } | |
1282 return; | |
1283 } | |
1284 | |
1285 extern void hermite2(); | |
1286 | |
1287 double blend(fp,evs,s,x,ll,ur,j,nt,t,what) | |
1288 fitpt *fp; | |
1289 evstruc *evs; | |
1290 double s, *x, *ll, *ur; | |
1291 int j, nt, *t, what; | |
1292 { | |
1293 int *ce, k, k1, m, nc, j0, j1; | |
1294 double v0, v1, xibar, g0[3], g1[3], gg[4], gp[4], phi[4]; | |
1295 ce = evs->ce; | |
1296 for (k=0; k<4; k++) /* North South East West */ | |
1297 { k1 = (k>1); | |
1298 v0 = ll[k1]; v1 = ur[k1]; | |
1299 j0 = ce[j+2*(k==0)+(k==2)]; | |
1300 j1 = ce[j+3-2*(k==1)-(k==3)]; | |
1301 xibar = (k%2==0) ? ur[k<2] : ll[k<2]; | |
1302 m = nt; | |
1303 while ((m>=0) && ((evs->s[t[m]] != (k<=1)) | (evs->sv[t[m]] != xibar))) m--; | |
1304 if (m >= 0) | |
1305 { m = (k%2==1) ? evs->lo[t[m]] : evs->hi[t[m]]; | |
1306 while (evs->s[m] != -1) | |
1307 m = (x[evs->s[m]] < evs->sv[m]) ? evs->lo[m] : evs->hi[m]; | |
1308 if (v0 < evptx(fp,ce[4*m+2*(k==1)+(k==3)],k1)) | |
1309 { j0 = ce[4*m+2*(k==1)+(k==3)]; | |
1310 v0 = evptx(fp,j0,k1); | |
1311 } | |
1312 if (evptx(fp,ce[4*m+3-2*(k==0)-(k==2)],k1) < v1) | |
1313 { j1 = ce[4*m+3-2*(k==0)-(k==2)]; | |
1314 v1 = evptx(fp,j1,k1); | |
1315 } | |
1316 } | |
1317 nc = exvval(fp,g0,j0,2,what,0); | |
1318 nc = exvval(fp,g1,j1,2,what,0); | |
1319 if (nc==1) | |
1320 gg[k] = linear_interp((x[(k>1)]-v0),v1-v0,g0[0],g1[0]); | |
1321 else | |
1322 { hermite2(x[(k>1)]-v0,v1-v0,phi); | |
1323 gg[k] = phi[0]*g0[0]+phi[1]*g1[0]+(phi[2]*g0[1+k1]+phi[3]*g1[1+k1])*(v1-v0); | |
1324 gp[k] = phi[0]*g0[2-k1] + phi[1]*g1[2-k1]; | |
1325 } | |
1326 } | |
1327 s = -s; | |
1328 if (nc==1) | |
1329 for (k=0; k<2; k++) | |
1330 s += linear_interp(x[k]-ll[k],ur[k]-ll[k],gg[3-2*k],gg[2-2*k]); | |
1331 else | |
1332 for (k=0; k<2; k++) /* EW NS */ | |
1333 { hermite2(x[k]-ll[k],ur[k]-ll[k],phi); | |
1334 s += phi[0]*gg[3-2*k] + phi[1]*gg[2-2*k] | |
1335 +(phi[2]*gp[3-2*k] + phi[3]*gp[2-2*k]) * (ur[k]-ll[k]); | |
1336 } | |
1337 return(s); | |
1338 } | |
1339 | |
1340 double kdtre_int(fp,evs,x,what) | |
1341 fitpt *fp; | |
1342 evstruc *evs; | |
1343 double *x; | |
1344 int what; | |
1345 { | |
1346 int *ce, k, vc, t[20], nt, nc, j, d; | |
1347 double *ll, *ur, ff, vv[64][64]; | |
1348 d = fp->d; | |
1349 vc = 1<<d; | |
1350 if (d > 6) { LERR(("d too large in kdint")); return(NOSLN); } | |
1351 | |
1352 /* descend the tree to find the terminal cell */ | |
1353 nt = 0; t[nt] = 0; k = 0; | |
1354 while (evs->s[k] != -1) | |
1355 { nt++; | |
1356 if (nt>=20) { LERR(("Too many levels in kdint")); return(NOSLN); } | |
1357 k = t[nt] = (x[evs->s[k]] < evs->sv[k]) ? evs->lo[k] : evs->hi[k]; | |
1358 } | |
1359 | |
1360 ce = &evs->ce[k*vc]; | |
1361 ll = evpt(fp,ce[0]); | |
1362 ur = evpt(fp,ce[vc-1]); | |
1363 nc = 0; | |
1364 for (j=0; j<vc; j++) nc = exvval(fp,vv[j],(int)ce[j],d,what,0); | |
1365 ff = rectcell_interp(x,vv,ll,ur,d,nc); | |
1366 | |
1367 if (d==2) ff = blend(fp,evs,ff,x,ll,ur,k*vc,nt,t,what); | |
1368 return(ff); | |
1369 } | |
1370 /* | |
1371 * Copyright 1996-2006 Catherine Loader. | |
1372 */ | |
1373 #include "lfev.h" | |
1374 | |
1375 /* | |
1376 * convert eval. structure string to numeric code. | |
1377 */ | |
1378 #define NETYPE 11 | |
1379 static char *etype[NETYPE]= { "tree", "phull", "data", "grid", "kdtree", | |
1380 "kdcenter", "cross", "preset", "xbar", "none", | |
1381 "sphere" }; | |
1382 static int evals[NETYPE]= { ETREE, EPHULL, EDATA, EGRID, EKDTR, | |
1383 EKDCE, ECROS, EPRES, EXBAR, ENONE, ESPHR }; | |
1384 int lfevstr(char *z) | |
1385 { return(pmatch(z, etype, evals, NETYPE, -1)); | |
1386 } | |
1387 | |
1388 void evstruc_init(evs) | |
1389 evstruc *evs; | |
1390 { int i; | |
1391 ev(evs) = ETREE; | |
1392 mk(evs) = 100; | |
1393 cut(evs) = 0.8; | |
1394 for (i=0; i<MXDIM; i++) | |
1395 { evs->fl[i] = evs->fl[i+MXDIM] = 0.0; | |
1396 evs->mg[i] = 10; | |
1397 } | |
1398 evs->nce = evs->ncm = 0; | |
1399 } | |
1400 | |
1401 int evstruc_reqi(nvm,ncm,vc) | |
1402 int nvm, ncm, vc; | |
1403 { return(ncm*vc+3*MAX(ncm,nvm)); | |
1404 } | |
1405 | |
1406 /* al=1: allows dynamic allocation. | |
1407 * al=0: inhibit. use with caution. | |
1408 */ | |
1409 void evstruc_alloc(evs,nvm,ncm,vc,al) | |
1410 evstruc *evs; | |
1411 int nvm, ncm, vc, al; | |
1412 { int rw, *k; | |
1413 | |
1414 if (al) | |
1415 { rw = evstruc_reqi(nvm,ncm,vc); | |
1416 if (evs->liw<rw) | |
1417 { evs->iwk = (int *)calloc(rw,sizeof(int)); | |
1418 if ( evs->iwk == NULL ) { | |
1419 printf("Problem allocating memory for evs->iwk\n");fflush(stdout); | |
1420 } | |
1421 evs->liw = rw; | |
1422 } | |
1423 } | |
1424 k = evs->iwk; | |
1425 evs->ce = k; k += vc*ncm; | |
1426 evs->s = k; k += MAX(ncm,nvm); | |
1427 evs->lo = k; k += MAX(ncm,nvm); | |
1428 evs->hi = k; k += MAX(ncm,nvm); | |
1429 } | |
1430 | |
1431 void guessnv(evs,sp,mdl,n,d,lw,nvc) | |
1432 evstruc *evs; | |
1433 smpar *sp; | |
1434 module *mdl; | |
1435 int n, d, *lw, *nvc; | |
1436 { int i, nvm, ncm, vc; | |
1437 | |
1438 npar(sp) = calcp(sp,d); | |
1439 switch(ev(evs)) | |
1440 { case ETREE: | |
1441 atree_guessnv(evs,&nvm,&ncm,&vc,d,nn(sp)); | |
1442 break; | |
1443 case EPHULL: | |
1444 nvm = ncm = mk(evs)*d; | |
1445 vc = d+1; | |
1446 break; | |
1447 case EDATA: | |
1448 case ECROS: | |
1449 nvm = n; | |
1450 ncm = vc = 0; | |
1451 break; | |
1452 case EKDTR: | |
1453 case EKDCE: | |
1454 kdtre_guessnv(evs,&nvm,&ncm,&vc,n,d,nn(sp)); | |
1455 break; | |
1456 case EGRID: | |
1457 nvm = 1; | |
1458 for (i=0; i<d; i++) nvm *= evs->mg[i]; | |
1459 ncm = 0; | |
1460 vc = 1<<d; | |
1461 break; | |
1462 case EXBAR: | |
1463 case ENONE: | |
1464 nvm = 1; | |
1465 ncm = vc = 0; | |
1466 break; | |
1467 case EPRES: | |
1468 nvm = evs->mg[0]; | |
1469 ncm = vc = 0; | |
1470 break; | |
1471 default: | |
1472 LERR(("guessnv: I don't know this evaluation structure.")); | |
1473 nvm = ncm = vc = 0; | |
1474 } | |
1475 | |
1476 lw[0] = des_reqd(n,npar(sp)); | |
1477 lw[1] = lfit_reqd(d,nvm,ncm,mdl); | |
1478 lw[2] = evstruc_reqi(nvm,ncm,vc); | |
1479 lw[6] = des_reqi(n,npar(sp)); | |
1480 lw[3] = pc_reqd(d,npar(sp)); | |
1481 lw[4] = mdl->keepv; | |
1482 lw[5] = mdl->keepc; | |
1483 | |
1484 if (nvc==NULL) return; | |
1485 nvc[0] = nvm; | |
1486 nvc[1] = ncm; | |
1487 nvc[2] = vc; | |
1488 nvc[3] = nvc[4] = 0; | |
1489 } | |
1490 | |
1491 /* | |
1492 * trchck checks the working space on the lfit structure | |
1493 * has space for nvm vertices and ncm cells. | |
1494 */ | |
1495 void lfit_alloc(lf) | |
1496 lfit *lf; | |
1497 { lf->fp.lwk = lf->fp.lev = lf->evs.liw = lf->pc.lwk = 0; | |
1498 lf->lf_init_id = LF_INIT_ID; | |
1499 } | |
1500 int lfit_reqd(d,nvm,ncm,mdl) | |
1501 int d, nvm, ncm; | |
1502 module *mdl; | |
1503 { int z; | |
1504 z = mdl->keepv; | |
1505 return(nvm*z+ncm); | |
1506 } | |
1507 | |
1508 void trchck(lf,nvm,ncm,vc) | |
1509 lfit *lf; | |
1510 int nvm, ncm, vc; | |
1511 { int rw, d, *k; | |
1512 double *z; | |
1513 | |
1514 if (lf->lf_init_id != LF_INIT_ID) lfit_alloc(lf); | |
1515 | |
1516 lf->fp.nvm = nvm; lf->evs.ncm = ncm; | |
1517 d = lf->lfd.d; | |
1518 | |
1519 if (lf->fp.lev < d*nvm) | |
1520 { lf->fp.xev = (double *)calloc(d*nvm,sizeof(double)); | |
1521 if ( lf->fp.xev == NULL ) { | |
1522 printf("Problem allocating memory for lf->fp.xev\n");fflush(stdout); | |
1523 } | |
1524 lf->fp.lev = d*nvm; | |
1525 } | |
1526 | |
1527 rw = lfit_reqd(d,nvm,ncm,&lf->mdl); | |
1528 if (lf->fp.lwk < rw) | |
1529 { | |
1530 lf->fp.coef = (double *)calloc(rw,sizeof(double)); | |
1531 if ( lf->fp.coef == NULL ) { | |
1532 printf("Problem allocating memory for lf->fp.coef\n");fflush(stdout); | |
1533 } | |
1534 lf->fp.lwk = rw; | |
1535 } | |
1536 z = lf->fp.wk = lf->fp.coef; | |
1537 | |
1538 lf->fp.h = NULL; | |
1539 if (!lf->mdl.isset) mut_printf("module not set.\n"); | |
1540 else | |
1541 { if (lf->mdl.alloc!=NULL) lf->mdl.alloc(lf); | |
1542 z += KEEPV(lf) * nvm; | |
1543 } | |
1544 lf->evs.sv = z; z += ncm; | |
1545 | |
1546 evstruc_alloc(&lf->evs,nvm,ncm,vc,1); | |
1547 } | |
1548 | |
1549 void data_guessnv(nvm,ncm,vc,n) | |
1550 int *nvm, *ncm, *vc, n; | |
1551 { *nvm = n; | |
1552 *ncm = *vc = 0; | |
1553 } | |
1554 | |
1555 void dataf(des,lf) | |
1556 design *des; | |
1557 lfit *lf; | |
1558 { | |
1559 int d, i, j, ncm, nv, vc; | |
1560 | |
1561 d = lf->lfd.d; | |
1562 data_guessnv(&nv,&ncm,&vc,lf->lfd.n); | |
1563 trchck(lf,nv,ncm,vc); | |
1564 | |
1565 for (i=0; i<nv; i++) | |
1566 for (j=0; j<d; j++) evptx(&lf->fp,i,j) = datum(&lf->lfd,j,i); | |
1567 for (i=0; i<nv; i++) | |
1568 { | |
1569 PROC_VERTEX(des,lf,i); | |
1570 lf->evs.s[i] = 0; | |
1571 } | |
1572 lf->fp.nv = lf->fp.nvm = nv; lf->evs.nce = 0; | |
1573 } | |
1574 | |
1575 void xbar_guessnv(nvm,ncm,vc) | |
1576 int *nvm, *ncm, *vc; | |
1577 { *nvm = 1; | |
1578 *ncm = *vc = 0; | |
1579 return; | |
1580 } | |
1581 | |
1582 void xbarf(des,lf) | |
1583 design *des; | |
1584 lfit *lf; | |
1585 { int i, d, nvm, ncm, vc; | |
1586 d = lf->lfd.d; | |
1587 xbar_guessnv(&nvm,&ncm,&vc); | |
1588 trchck(lf,1,0,0); | |
1589 for (i=0; i<d; i++) evptx(&lf->fp,0,i) = lf->pc.xbar[i]; | |
1590 PROC_VERTEX(des,lf,0); | |
1591 lf->evs.s[0] = 0; | |
1592 lf->fp.nv = 1; lf->evs.nce = 0; | |
1593 } | |
1594 | |
1595 void preset(des,lf) | |
1596 design *des; | |
1597 lfit *lf; | |
1598 { int i, nv; | |
1599 | |
1600 nv = lf->fp.nvm; | |
1601 trchck(lf,nv,0,0); | |
1602 for (i=0; i<nv; i++) | |
1603 { | |
1604 PROC_VERTEX(des,lf,i); | |
1605 lf->evs.s[i] = 0; | |
1606 } | |
1607 lf->fp.nv = nv; lf->evs.nce = 0; | |
1608 } | |
1609 | |
1610 void crossf(des,lf) | |
1611 design *des; | |
1612 lfit *lf; | |
1613 { int d, i, j, n, nv, ncm, vc; | |
1614 double w; | |
1615 | |
1616 n = lf->lfd.n; d = lf->lfd.d; | |
1617 data_guessnv(&nv,&ncm,&vc,n); | |
1618 trchck(lf,nv,ncm,vc); | |
1619 | |
1620 if (lf->lfd.w==NULL) LERR(("crossf() needs prior weights")); | |
1621 for (i=0; i<n; i++) | |
1622 for (j=0; j<d; j++) evptx(&lf->fp,i,j) = datum(&lf->lfd,j,i); | |
1623 for (i=0; i<n; i++) | |
1624 { lf->evs.s[i] = 0; | |
1625 w = prwt(&lf->lfd,i); | |
1626 lf->lfd.w[i] = 0; | |
1627 PROC_VERTEX(des,lf,i); | |
1628 lf->lfd.w[i] = w; | |
1629 } | |
1630 lf->fp.nv = n; lf->evs.nce = 0; | |
1631 } | |
1632 | |
1633 void gridf(des,lf) | |
1634 design *des; | |
1635 lfit *lf; | |
1636 { int d, i, j, nv, u0, u1, z; | |
1637 nv = 1; d = lf->lfd.d; | |
1638 for (i=0; i<d; i++) | |
1639 { if (lf->evs.mg[i]==0) | |
1640 lf->evs.mg[i] = 2+(int)((lf->evs.fl[i+d]-lf->evs.fl[i])/(lf->lfd.sca[i]*cut(&lf->evs))); | |
1641 nv *= lf->evs.mg[i]; | |
1642 } | |
1643 trchck(lf,nv,0,1<<d); | |
1644 for (i=0; i<nv; i++) | |
1645 { z = i; | |
1646 for (j=0; j<d; j++) | |
1647 { u0 = z%lf->evs.mg[j]; | |
1648 u1 = lf->evs.mg[j]-1-u0; | |
1649 evptx(&lf->fp,i,j) = (lf->evs.mg[j]==1) ? lf->evs.fl[j] : | |
1650 (u1*lf->evs.fl[j]+u0*lf->evs.fl[j+d])/(lf->evs.mg[j]-1); | |
1651 z = z/lf->evs.mg[j]; | |
1652 } | |
1653 lf->evs.s[i] = 0; | |
1654 PROC_VERTEX(des,lf,i); | |
1655 } | |
1656 lf->fp.nv = nv; lf->evs.nce = 0; | |
1657 } | |
1658 | |
1659 int findpt(fp,evs,i0,i1) | |
1660 fitpt *fp; | |
1661 evstruc *evs; | |
1662 int i0, i1; | |
1663 { int i; | |
1664 if (i0>i1) ISWAP(i0,i1); | |
1665 for (i=i1+1; i<fp->nv; i++) | |
1666 if ((evs->lo[i]==i0) && (evs->hi[i]==i1)) return(i); | |
1667 return(-1); | |
1668 } | |
1669 | |
1670 /* | |
1671 add a new vertex at the midpoint of (x[i0],x[i1]). | |
1672 return the vertex number. | |
1673 */ | |
1674 int newsplit(des,lf,i0,i1,pv) | |
1675 design *des; | |
1676 lfit *lf; | |
1677 int i0, i1, pv; | |
1678 { int i, nv; | |
1679 | |
1680 i = findpt(&lf->fp,&lf->evs,i0,i1); | |
1681 if (i>=0) return(i); | |
1682 | |
1683 if (i0>i1) ISWAP(i0,i1); | |
1684 nv = lf->fp.nv; | |
1685 | |
1686 /* the point is new. Now check we have space for the new point. */ | |
1687 if (nv>=lf->fp.nvm) | |
1688 { | |
1689 LERR(("newsplit: out of vertex space")); | |
1690 return(-1); | |
1691 } | |
1692 | |
1693 /* compute the new point, and evaluate the fit */ | |
1694 lf->evs.lo[nv] = i0; | |
1695 lf->evs.hi[nv] = i1; | |
1696 for (i=0; i<lf->fp.d; i++) | |
1697 evptx(&lf->fp,nv,i) = (evptx(&lf->fp,i0,i)+evptx(&lf->fp,i1,i))/2; | |
1698 if (pv) /* pseudo vertex */ | |
1699 { lf->fp.h[nv] = (lf->fp.h[i0]+lf->fp.h[i1])/2; | |
1700 lf->evs.s[nv] = 1; /* pseudo-vertex */ | |
1701 } | |
1702 else /* real vertex */ | |
1703 { | |
1704 PROC_VERTEX(des,lf,nv); | |
1705 lf->evs.s[nv] = 0; | |
1706 } | |
1707 lf->fp.nv++; | |
1708 | |
1709 return(nv); | |
1710 } | |
1711 /* | |
1712 * Copyright 1996-2006 Catherine Loader. | |
1713 */ | |
1714 /* | |
1715 * Functions for constructing the fit and | |
1716 * interpolating on the circle/sphere. d=2 only. | |
1717 */ | |
1718 | |
1719 #include "lfev.h" | |
1720 | |
1721 /* | |
1722 * Guess the number of fitting points. | |
1723 */ | |
1724 void sphere_guessnv(nvm,ncm,vc,mg) | |
1725 int *nvm, *ncm, *vc, *mg; | |
1726 { *nvm = mg[1]*(mg[0]+1); | |
1727 *ncm = 0; | |
1728 *vc = 0; | |
1729 } | |
1730 | |
1731 void sphere_start(des,lf) | |
1732 design *des; | |
1733 lfit *lf; | |
1734 { int d, i, j, ct, nv, ncm, vc, *mg; | |
1735 double rmin, rmax, *orig, r, th, c, s; | |
1736 | |
1737 mg = mg(&lf->evs); | |
1738 sphere_guessnv(&nv,&ncm,&vc,mg); | |
1739 trchck(lf,nv,0,0); | |
1740 d = lf->lfd.d; | |
1741 | |
1742 rmin = lf->evs.fl[0]; | |
1743 rmax = lf->evs.fl[1]; | |
1744 orig = &lf->evs.fl[2]; | |
1745 rmin = 0; rmax = 1; orig[0] = orig[1] = 0.0; | |
1746 | |
1747 ct = 0; | |
1748 for (i=0; i<mg[1]; i++) | |
1749 { th = 2*PI*i/mg[1]; | |
1750 c = cos(th); | |
1751 s = sin(th); | |
1752 for (j=0; j<=mg[0]; j++) | |
1753 { r = rmin + (rmax-rmin)*j/mg[0]; | |
1754 evptx(&lf->fp,ct,0) = orig[0] + r*c; | |
1755 evptx(&lf->fp,ct,1) = orig[1] + r*s; | |
1756 PROC_VERTEX(des,lf,ct); | |
1757 ct++; | |
1758 } | |
1759 } | |
1760 lf->fp.nv = ct; | |
1761 lf->evs.nce = 0; | |
1762 } | |
1763 | |
1764 double sphere_int(lf,x,what) | |
1765 lfit *lf; | |
1766 double *x; | |
1767 int what; | |
1768 { double rmin, rmax, *orig, dx, dy, r, th, th0, th1; | |
1769 double v[64][64], c0, c1, s0, s1, r0, r1, d0, d1; | |
1770 double ll[2], ur[2], xx[2]; | |
1771 int i0, j0, i1, j1, *mg, nc, ce[4]; | |
1772 | |
1773 rmin = lf->evs.fl[0]; | |
1774 rmax = lf->evs.fl[1]; | |
1775 orig = &lf->evs.fl[2]; | |
1776 rmin = 0; rmax = 1; orig[0] = orig[1] = 0.0; | |
1777 mg = mg(&lf->evs); | |
1778 | |
1779 dx = x[0] - orig[0]; | |
1780 dy = x[1] - orig[1]; | |
1781 r = sqrt(dx*dx+dy*dy); | |
1782 th = atan2(dy,dx); /* between -pi and pi */ | |
1783 | |
1784 i0 = (int)floor(mg[1]*th/(2*PI)) % mg[1]; | |
1785 j0 = (int)(mg[0]*(r-rmin)/(rmax-rmin)); | |
1786 | |
1787 i1 = (i0+1) % mg[1]; | |
1788 j1 = j0+1; if (j1>mg[0]) { j0 = mg[0]-1; j1 = mg[0]; } | |
1789 | |
1790 ce[0] = i0*(mg[0]+1)+j0; | |
1791 ce[1] = i0*(mg[0]+1)+j1; | |
1792 ce[2] = i1*(mg[0]+1)+j0; | |
1793 ce[3] = i1*(mg[0]+1)+j1; | |
1794 nc = exvval(&lf->fp,v[0],ce[0],2,what,1); | |
1795 nc = exvval(&lf->fp,v[1],ce[1],2,what,1); | |
1796 nc = exvval(&lf->fp,v[2],ce[2],2,what,1); | |
1797 nc = exvval(&lf->fp,v[3],ce[3],2,what,1); | |
1798 | |
1799 th0 = 2*PI*i0/mg[1]; c0 = cos(th0); s0 = sin(th0); | |
1800 th1 = 2*PI*i1/mg[1]; c1 = cos(th1); s1 = sin(th1); | |
1801 r0 = rmin + j0*(rmax-rmin)/mg[0]; | |
1802 r1 = rmin + j1*(rmax-rmin)/mg[0]; | |
1803 | |
1804 d0 = c0*v[0][1] + s0*v[0][2]; | |
1805 d1 = r0*(c0*v[0][2]-s0*v[0][1]); | |
1806 v[0][1] = d0; v[0][2] = d1; | |
1807 | |
1808 d0 = c0*v[1][1] + s0*v[1][2]; | |
1809 d1 = r1*(c0*v[1][2]-s0*v[1][1]); | |
1810 v[1][1] = d0; v[1][2] = d1; | |
1811 | |
1812 d0 = c1*v[2][1] + s1*v[2][2]; | |
1813 d1 = r0*(c1*v[2][2]-s1*v[2][1]); | |
1814 v[2][1] = d0; v[2][2] = d1; | |
1815 | |
1816 d0 = c1*v[3][1] + s1*v[3][2]; | |
1817 d1 = r1*(c1*v[3][2]-s1*v[3][1]); | |
1818 v[3][1] = d0; v[3][2] = d1; | |
1819 | |
1820 xx[0] = r; xx[1] = th; | |
1821 ll[0] = r0; ll[1] = th0; | |
1822 ur[0] = r1; ur[1] = th1; | |
1823 return(rectcell_interp(xx,v,ll,ur,2,nc)); | |
1824 } | |
1825 /* | |
1826 * Copyright 1996-2006 Catherine Loader. | |
1827 */ | |
1828 #include "lfev.h" | |
1829 | |
1830 void solve(A,b,d) /* this is crude! A organized by column. */ | |
1831 double *A, *b; | |
1832 int d; | |
1833 { int i, j, k; | |
1834 double piv; | |
1835 for (i=0; i<d; i++) | |
1836 { piv = A[(d+1)*i]; | |
1837 for (j=i; j<d; j++) A[j*d+i] /= piv; | |
1838 b[i] /= piv; | |
1839 for (j=0; j<d; j++) if (j != i) | |
1840 { piv = A[i*d+j]; | |
1841 A[i*d+j] = 0; | |
1842 for (k=i+1; k<d; k++) | |
1843 A[k*d+j] -= piv*A[k*d+i]; | |
1844 b[j] -= piv*b[i]; | |
1845 } | |
1846 } | |
1847 } | |
1848 | |
1849 void triang_guessnv(nvm,ncm,vc,d,mk) | |
1850 int *nvm, *ncm, *vc, d, mk; | |
1851 { *nvm = *ncm = mk*d; | |
1852 *vc = d+1; | |
1853 return; | |
1854 } | |
1855 | |
1856 int triang_split(lf,ce,le) | |
1857 lfit *lf; | |
1858 double *le; | |
1859 int *ce; | |
1860 { int d, i, j, k, nts, vc; | |
1861 double di, dfx[MXDIM]; | |
1862 nts = 0; d = lf->fp.d; vc = d+1; | |
1863 for (i=0; i<d; i++) | |
1864 for (j=i+1; j<=d; j++) | |
1865 { for (k=0; k<d; k++) | |
1866 dfx[k] = evptx(&lf->fp,ce[i],k)-evptx(&lf->fp,ce[j],k); | |
1867 di = rho(dfx,lf->lfd.sca,d,KSPH,NULL); | |
1868 le[i*vc+j] = le[j*vc+i] = di/MIN(lf->fp.h[ce[i]],lf->fp.h[ce[j]]); | |
1869 nts = nts || le[i*vc+j]>cut(&lf->evs); | |
1870 } | |
1871 return(nts); | |
1872 } | |
1873 | |
1874 void resort(pv,xev,dig) | |
1875 double *xev; | |
1876 int *pv, *dig; | |
1877 { double d0, d1, d2; | |
1878 int i; | |
1879 d0 = d1 = d2 = 0; | |
1880 for (i=0; i<3; i++) | |
1881 { d0 += (xev[3*pv[11]+i]-xev[3*pv[1]+i])*(xev[3*pv[11]+i]-xev[3*pv[1]+i]); | |
1882 d1 += (xev[3*pv[ 7]+i]-xev[3*pv[2]+i])*(xev[3*pv[ 7]+i]-xev[3*pv[2]+i]); | |
1883 d2 += (xev[3*pv[ 6]+i]-xev[3*pv[3]+i])*(xev[3*pv[ 6]+i]-xev[3*pv[3]+i]); | |
1884 } | |
1885 if ((d0<=d1) & (d0<=d2)) | |
1886 { dig[0] = pv[1]; dig[1] = pv[11]; | |
1887 dig[2] = pv[2]; dig[3] = pv[7]; | |
1888 dig[4] = pv[3]; dig[5] = pv[6]; | |
1889 } | |
1890 else if (d1<=d2) | |
1891 { dig[0] = pv[2]; dig[1] = pv[7]; | |
1892 dig[2] = pv[1]; dig[3] = pv[11]; | |
1893 dig[4] = pv[3]; dig[5] = pv[6]; | |
1894 } | |
1895 else | |
1896 { dig[0] = pv[3]; dig[1] = pv[6]; | |
1897 dig[2] = pv[2]; dig[3] = pv[7]; | |
1898 dig[4] = pv[1]; dig[5] = pv[11]; | |
1899 } | |
1900 } | |
1901 | |
1902 void triang_grow(des,lf,ce,ct,term) | |
1903 design *des; | |
1904 lfit *lf; | |
1905 int *ce, *ct, *term; | |
1906 { double le[(1+MXDIM)*(1+MXDIM)], ml; | |
1907 int d, i, j, im, jm, vc, pv[(1+MXDIM)*(1+MXDIM)], dig[6]; | |
1908 int nce[1+MXDIM]; | |
1909 if (lf_error) return; | |
1910 d = lf->fp.d; vc = d+1; | |
1911 if (!triang_split(lf,ce,le)) | |
1912 { if (ct != NULL) | |
1913 { for (i=0; i<vc; i++) term[*ct*vc+i] = ce[i]; | |
1914 (*ct)++; | |
1915 } | |
1916 return; | |
1917 } | |
1918 if (d>3) | |
1919 { ml = 0; | |
1920 for (i=0; i<d; i++) | |
1921 for (j=i+1; j<vc; j++) | |
1922 if (le[i*vc+j]>ml) { ml = le[i*vc+j]; im = i; jm = j; } | |
1923 pv[0] = newsplit(des,lf,(int)ce[im],(int)ce[jm],0); | |
1924 for (i=0; i<vc; i++) nce[i] = ce[i]; | |
1925 nce[im] = pv[0]; triang_grow(des,lf,nce,ct,term); nce[im] = ce[im]; | |
1926 nce[jm] = pv[0]; triang_grow(des,lf,nce,ct,term); | |
1927 return; | |
1928 } | |
1929 | |
1930 for (i=0; i<d; i++) | |
1931 for (j=i+1; j<=d; j++) | |
1932 pv[i*vc+j] = pv[j*vc+i] | |
1933 = newsplit(des,lf,(int)ce[i],(int)ce[j],le[i*vc+j]<=cut(&lf->evs)); | |
1934 for (i=0; i<=d; i++) /* corners */ | |
1935 { for (j=0; j<=d; j++) nce[j] = (j==i) ? ce[i] : pv[i*vc+j]; | |
1936 triang_grow(des,lf,nce,ct,term); | |
1937 } | |
1938 | |
1939 if (d==2) /* center for d=2 */ | |
1940 { nce[0] = pv[5]; nce[1] = pv[2]; nce[2] = pv[1]; | |
1941 triang_grow(des,lf,nce,ct,term); | |
1942 } | |
1943 if (d==3) /* center for d=3 */ | |
1944 { resort(pv,evp(&lf->fp),dig); | |
1945 nce[0] = dig[0]; nce[1] = dig[1]; | |
1946 nce[2] = dig[2]; nce[3] = dig[4]; triang_grow(des,lf,nce,ct,term); | |
1947 nce[2] = dig[5]; nce[3] = dig[3]; triang_grow(des,lf,nce,ct,term); | |
1948 nce[2] = dig[2]; nce[3] = dig[5]; triang_grow(des,lf,nce,ct,term); | |
1949 nce[2] = dig[4]; nce[3] = dig[3]; triang_grow(des,lf,nce,ct,term); | |
1950 } | |
1951 } | |
1952 | |
1953 void triang_descend(tr,xa,ce) | |
1954 lfit *tr; | |
1955 double *xa; | |
1956 int *ce; | |
1957 { double le[(1+MXDIM)*(1+MXDIM)], ml; | |
1958 int d, vc, i, j, im, jm, pv[(1+MXDIM)*(1+MXDIM)]; | |
1959 design *des; | |
1960 des = NULL; | |
1961 if (!triang_split(tr,ce,le)) return; | |
1962 d = tr->fp.d; vc = d+1; | |
1963 | |
1964 if (d>3) /* split longest edge */ | |
1965 { ml = 0; | |
1966 for (i=0; i<d; i++) | |
1967 for (j=i+1; j<vc; j++) | |
1968 if (le[i*vc+j]>ml) { ml = le[i*vc+j]; im = i; jm = j; } | |
1969 pv[0] = newsplit(des,tr,(int)ce[im],(int)ce[jm],0); | |
1970 if (xa[im]>xa[jm]) | |
1971 { xa[im] -= xa[jm]; xa[jm] *= 2; ce[jm] = pv[0]; } | |
1972 else | |
1973 { xa[jm] -= xa[im]; xa[im] *= 2; ce[im] = pv[0]; } | |
1974 triang_descend(tr,xa,ce); | |
1975 return; | |
1976 } | |
1977 | |
1978 for (i=0; i<d; i++) | |
1979 for (j=i+1; j<=d; j++) | |
1980 pv[i*vc+j] = pv[j*vc+i] | |
1981 = newsplit(des,tr,(int)ce[i],(int)ce[j],le[i*d+j]<=cut(&tr->evs)); | |
1982 for (i=0; i<=d; i++) if (xa[i]>=0.5) /* in corner */ | |
1983 { for (j=0; j<=d; j++) | |
1984 { if (i!=j) ce[j] = pv[i*vc+j]; | |
1985 xa[j] = 2*xa[j]; | |
1986 } | |
1987 xa[i] -= 1; | |
1988 triang_descend(tr,xa,ce); | |
1989 return; | |
1990 } | |
1991 if (d==1) { LERR(("weights sum to < 1")); } | |
1992 if (d==2) /* center */ | |
1993 { ce[0] = pv[5]; xa[0] = 1-2*xa[0]; | |
1994 ce[1] = pv[2]; xa[1] = 1-2*xa[1]; | |
1995 ce[2] = pv[1]; xa[2] = 1-2*xa[2]; | |
1996 triang_descend(tr,xa,ce); | |
1997 } | |
1998 if (d==3) /* center */ | |
1999 { double z; int dig[6]; | |
2000 resort(pv,evp(&tr->fp),dig); | |
2001 ce[0] = dig[0]; ce[1] = dig[1]; | |
2002 xa[0] *= 2; xa[1] *= 2; xa[2] *= 2; xa[3] *= 2; | |
2003 if (xa[0]+xa[2]>=1) | |
2004 { if (xa[0]+xa[3]>=1) | |
2005 { ce[2] = dig[2]; ce[3] = dig[4]; | |
2006 z = xa[0]; | |
2007 xa[3] += z-1; xa[2] += z-1; xa[0] = xa[1]; xa[1] = 1-z; | |
2008 } | |
2009 else | |
2010 { ce[2] = dig[2]; ce[3] = dig[5]; | |
2011 z = xa[3]; xa[3] = xa[1]+xa[2]-1; xa[1] = z; | |
2012 z = xa[2]; xa[2] += xa[0]-1; xa[0] = 1-z; | |
2013 } } | |
2014 else | |
2015 { if (xa[1]+xa[2]>=1) | |
2016 { ce[2] = dig[5]; ce[3] = dig[3]; | |
2017 xa[1] = 1-xa[1]; xa[2] -= xa[1]; xa[3] -= xa[1]; | |
2018 } | |
2019 else | |
2020 { ce[2] = dig[4]; ce[3] = dig[3]; | |
2021 z = xa[3]; xa[3] += xa[1]-1; xa[1] = xa[2]; | |
2022 xa[2] = z+xa[0]-1; xa[0] = 1-z; | |
2023 } } | |
2024 triang_descend(tr,xa,ce); | |
2025 } } | |
2026 | |
2027 void covrofdata(lfd,V,mn) /* covar of data; mean in mn */ | |
2028 lfdata *lfd; | |
2029 double *V, *mn; | |
2030 { int d, i, j, k; | |
2031 double s; | |
2032 s = 0; d = lfd->d; | |
2033 for (i=0; i<d*d; i++) V[i] = 0; | |
2034 for (i=0; i<lfd->n; i++) | |
2035 { s += prwt(lfd,i); | |
2036 for (j=0; j<d; j++) | |
2037 for (k=0; k<d; k++) | |
2038 V[j*d+k] += prwt(lfd,i)*(datum(lfd,j,i)-mn[j])*(datum(lfd,k,i)-mn[k]); | |
2039 } | |
2040 for (i=0; i<d*d; i++) V[i] /= s; | |
2041 } | |
2042 | |
2043 int intri(x,w,xev,xa,d) /* is x in triangle bounded by xd[0..d-1]? */ | |
2044 double *x, *xev, *xa; | |
2045 int *w, d; | |
2046 { int i, j; | |
2047 double eps, *r, xd[MXDIM*MXDIM]; | |
2048 eps = 1.0e-10; | |
2049 r = &xev[w[d]*d]; | |
2050 for (i=0; i<d; i++) | |
2051 { xa[i] = x[i]-r[i]; | |
2052 for (j=0; j<d; j++) xd[i*d+j] = xev[w[i]*d+j]-r[j]; | |
2053 } | |
2054 solve(xd,xa,d); | |
2055 xa[d] = 1.0; | |
2056 for (i=0; i<d; i++) xa[d] -= xa[i]; | |
2057 for (i=0; i<=d; i++) if ((xa[i]<-eps) | (xa[i]>1+eps)) return(0); | |
2058 return(1); | |
2059 } | |
2060 | |
2061 void triang_start(des,lf) /* Triangulation with polyhedral start */ | |
2062 design *des; | |
2063 lfit *lf; | |
2064 { | |
2065 int i, j, k, n, d, nc, nvm, ncm, vc; | |
2066 int *ce, ed[1+MXDIM]; | |
2067 double V[MXDIM*MXDIM], P[MXDIM*MXDIM], sigma, z[MXDIM], xa[1+MXDIM], *xev; | |
2068 xev = evp(&lf->fp); | |
2069 d = lf->lfd.d; n = lf->lfd.n; | |
2070 lf->fp.nv = nc = 0; | |
2071 | |
2072 triang_guessnv(&nvm,&ncm,&vc,d,mk(&lf->evs)); | |
2073 trchck(lf,nvm,ncm,vc); | |
2074 | |
2075 ce = lf->evs.ce; | |
2076 for (j=0; j<d; j++) xev[j] = lf->pc.xbar[j]; | |
2077 lf->fp.nv = 1; | |
2078 covrofdata(&lf->lfd,V,xev); /* fix this with scaling */ | |
2079 eig_dec(V,P,d); | |
2080 | |
2081 for (i=0; i<d; i++) /* add vertices +- 2sigma*eigenvect */ | |
2082 { sigma = sqrt(V[i*(d+1)]); | |
2083 for (j=0; j<d; j++) | |
2084 xev[lf->fp.nv*d+j] = xev[j]-2*sigma*P[j*d+i]; | |
2085 lf->fp.nv++; | |
2086 for (j=0; j<d; j++) | |
2087 xev[lf->fp.nv*d+j] = xev[j]+2*sigma*P[j*d+i]; | |
2088 lf->fp.nv++; | |
2089 } | |
2090 | |
2091 for (i=0; i<n; i++) /* is point i inside? */ | |
2092 { ed[0] = 0; | |
2093 for (j=0; j<d; j++) | |
2094 { z[j] = 0; | |
2095 for (k=0; k<d; k++) z[j] += P[k*d+j]*(datum(&lf->lfd,k,i)-xev[k]); | |
2096 ed[j+1] = 2*j+1+(z[j]>0); | |
2097 for (k=0; k<d; k++) z[j] = datum(&lf->lfd,j,i); | |
2098 } | |
2099 k = intri(z,ed,xev,xa,d); | |
2100 if (xa[0]<0) | |
2101 { for (j=1; j<=d; j++) | |
2102 for (k=0; k<d; k++) | |
2103 xev[ed[j]*d+k] = xa[0]*xev[k]+(1-xa[0])*xev[ed[j]*d+k]; | |
2104 } | |
2105 } | |
2106 | |
2107 nc = 1<<d; /* create initial cells */ | |
2108 for (i=0; i<nc; i++) | |
2109 { ce[i*vc] = 0; k = i; | |
2110 for (j=0; j<d; j++) | |
2111 { ce[i*vc+j+1] = 2*j+(k%2)+1; | |
2112 k>>=1; | |
2113 } | |
2114 } | |
2115 | |
2116 for (i=0; i<lf->fp.nv; i++) | |
2117 { PROC_VERTEX(des,lf,i); | |
2118 if (lf_error) return; | |
2119 lf->evs.s[i] = 0; | |
2120 } | |
2121 for (i=0; i<nc; i++) | |
2122 triang_grow(des,lf,&ce[i*vc],NULL,NULL); | |
2123 lf->evs.nce = nc; | |
2124 } | |
2125 | |
2126 double triang_cubicint(v,vv,w,d,nc,xxa) | |
2127 double *v, *vv, *xxa; | |
2128 int *w, d, nc; | |
2129 { double sa, lb, *vert0, *vert1, *vals0, *vals1, deriv0, deriv1; | |
2130 int i, j, k; | |
2131 if (nc==1) /* linear interpolate */ | |
2132 { sa = 0; | |
2133 for (i=0; i<=d; i++) sa += xxa[i]*vv[i]; | |
2134 return(sa); | |
2135 } | |
2136 sa = 1.0; | |
2137 for (j=d; j>0; j--) /* eliminate v[w[j]] */ | |
2138 { lb = xxa[j]/sa; | |
2139 for (k=0; k<j; k++) /* Interpolate edge v[w[k]],v[w[j]] */ | |
2140 { vert0 = &v[w[k]*d]; | |
2141 vert1 = &v[w[j]*d]; | |
2142 vals0 = &vv[k*nc]; | |
2143 vals1 = &vv[j*nc]; | |
2144 deriv0 = deriv1 = 0; | |
2145 for (i=0; i<d; i++) | |
2146 { deriv0 += (vert1[i]-vert0[i])*vals0[i+1]; | |
2147 deriv1 += (vert1[i]-vert0[i])*vals1[i+1]; | |
2148 } | |
2149 vals0[0] = cubic_interp(lb,vals0[0],vals1[0],deriv0,deriv1); | |
2150 for (i=1; i<=d; i++) | |
2151 vals0[i] = (1-lb)*((1-lb)*vals0[i]+lb*vals1[i]); | |
2152 } | |
2153 sa -= xxa[j]; | |
2154 if (sa<=0) j = 0; | |
2155 } | |
2156 return(vals0[0]); | |
2157 } | |
2158 | |
2159 double triang_clotoch(xev,vv,ce,p,xxa) | |
2160 double *xev, *vv, *xxa; | |
2161 int *ce, p; | |
2162 { double cfo[3], cfe[3], cg[9], *va, *vb, *vc, | |
2163 l0, nm[3], na, nb, nc, *xl, *xr, *xz, d0, d1, lb, dlt, gam; | |
2164 int i, w[3], cfl, cfr; | |
2165 if (p==1) | |
2166 return(xxa[0]*vv[0]+xxa[1]*vv[1]+xxa[2]*vv[2]); | |
2167 if (xxa[2]<=MIN(xxa[0],xxa[1])) | |
2168 { va = &xev[2*ce[0]]; vb = &xev[2*ce[1]]; vc = &xev[2*ce[2]]; | |
2169 w[0] = 0; w[1] = 3; w[2] = 6; | |
2170 } | |
2171 else | |
2172 if (xxa[1]<xxa[0]) | |
2173 { w[0] = 0; w[1] = 6; w[2] = 3; | |
2174 va = &xev[2*ce[0]]; vb = &xev[2*ce[2]]; vc = &xev[2*ce[1]]; | |
2175 lb = xxa[1]; xxa[1] = xxa[2]; xxa[2] = lb; | |
2176 } | |
2177 else | |
2178 { w[0] = 6; w[1] = 3; w[2] = 0; | |
2179 va = &xev[2*ce[2]]; vb = &xev[2*ce[1]]; vc = &xev[2*ce[0]]; | |
2180 lb = xxa[0]; xxa[0] = xxa[2]; xxa[2] = lb; | |
2181 } | |
2182 | |
2183 /* set cg to values and derivatives on standard triangle */ | |
2184 for (i=0; i<3; i++) | |
2185 { cg[3*i] = vv[w[i]]; | |
2186 cg[3*i+1] = ((vb[0]-va[0])*vv[w[i]+1] | |
2187 +(vb[1]-va[1])*vv[w[i]+2])/2; /* df/dx */ | |
2188 cg[3*i+2] = ((2*vc[0]-vb[0]-va[0])*vv[w[i]+1] | |
2189 +(2*vc[1]-vb[1]-va[1])*vv[w[i]+2])/2.0; /* sqrt{3} df/dy */ | |
2190 } | |
2191 dlt = (vb[0]-va[0])*(vc[1]-va[1])-(vc[0]-va[0])*(vb[1]-va[1]); | |
2192 /* Twice area; +ve if abc antic.wise -ve is abc c.wise */ | |
2193 cfo[0] = (cg[0]+cg[3]+cg[6])/3; | |
2194 cfo[1] = (2*cg[0]-cg[3]-cg[6])/4; | |
2195 cfo[2] = (2*cg[3]-cg[0]-cg[6])/4; | |
2196 na = -cg[1]+cg[2]; /* perp. deriv, rel. length 2 */ | |
2197 nb = -cg[4]-cg[5]; | |
2198 nc = 2*cg[7]; | |
2199 cfo[1] += (nb-nc)/16; | |
2200 cfo[2] += (nc-na)/16; | |
2201 na = -cg[1]-cg[2]/3.0; /* derivatives back to origin */ | |
2202 nb = cg[4]-cg[5]/3.0; | |
2203 nc = cg[8]/1.5; | |
2204 cfo[0] -= (na+nb+nc)*7/54; | |
2205 cfo[1] += 13*(nb+nc-2*na)/144; | |
2206 cfo[2] += 13*(na+nc-2*nb)/144; | |
2207 for (i=0; i<3; i++) | |
2208 { /* Outward normals by linear interpolation on original triangle. | |
2209 Convert to outward normals on standard triangle. | |
2210 Actually, computed to opposite corner */ | |
2211 switch(i) | |
2212 { case 0: xl = vc; xr = vb; xz = va; cfl = w[2]; cfr = w[1]; | |
2213 break; | |
2214 case 1: xl = va; xr = vc; xz = vb; cfl = w[0]; cfr = w[2]; | |
2215 break; | |
2216 case 2: xl = vb; xr = va; xz = vc; cfl = w[1]; cfr = w[0]; | |
2217 break; | |
2218 } | |
2219 na = xr[0]-xl[0]; nb = xr[1]-xl[1]; | |
2220 lb = na*na+nb*nb; | |
2221 d0 = 1.5*(vv[cfr]-vv[cfl]) - 0.25*(na*(vv[cfl+1]+vv[cfr+1]) | |
2222 +nb*(vv[cfl+2]+vv[cfr+2])); | |
2223 d1 = 0.5*( na*(vv[cfl+2]+vv[cfr+2])-nb*(vv[cfl+1]+vv[cfr+1]) ); | |
2224 l0 = (xz[0]-xl[0])*na+(xz[1]-xl[1])*nb-lb/2; | |
2225 nm[i] = (d1*dlt-l0*d0)/lb; | |
2226 } | |
2227 cfo[0] -= (nm[0]+nm[1]+nm[2])*4/81; | |
2228 cfo[1] += (2*nm[0]-nm[1]-nm[2])/27; | |
2229 cfo[2] += (2*nm[1]-nm[0]-nm[2])/27; | |
2230 | |
2231 gam = xxa[0]+xxa[1]-2*xxa[2]; | |
2232 if (gam==0) return(cfo[0]); | |
2233 lb = (xxa[0]-xxa[2])/gam; | |
2234 d0 = -2*cg[4]; d1 = -2*cg[1]; | |
2235 cfe[0] = cubic_interp(lb,cg[3],cg[0],d0,d1); | |
2236 cfe[1] = cubintd(lb,cg[3],cg[0],d0,d1); | |
2237 cfe[2] = -(1-lb)*(1-2*lb)*cg[5] + 4*lb*(1-lb)*nm[2] - lb*(2*lb-1)*cg[2]; | |
2238 d0 = 2*(lb*cfo[1]+(1-lb)*cfo[2]); | |
2239 d1 = (lb-0.5)*cfe[1]+cfe[2]/3.0; | |
2240 return(cubic_interp(gam,cfo[0],cfe[0],d0,d1)); | |
2241 } | |
2242 | |
2243 int triang_getvertexvals(fp,evs,vv,i,what) | |
2244 fitpt *fp; | |
2245 evstruc *evs; | |
2246 double *vv; | |
2247 int i, what; | |
2248 { double dx, P, le, vl[1+MXDIM], vh[1+MXDIM]; | |
2249 int d, il, ih, j, nc; | |
2250 d = fp->d; | |
2251 if (evs->s[i]==0) return(exvval(fp,vv,i,d,what,0)); | |
2252 | |
2253 il = evs->lo[i]; nc = triang_getvertexvals(fp,evs,vl,il,what); | |
2254 ih = evs->hi[i]; nc = triang_getvertexvals(fp,evs,vh,ih,what); | |
2255 vv[0] = (vl[0]+vh[0])/2; | |
2256 if (nc==1) return(nc); | |
2257 P = 1.5*(vh[0]-vl[0]); | |
2258 le = 0.0; | |
2259 for (j=0; j<d; j++) | |
2260 { dx = evptx(fp,ih,j)-evptx(fp,il,j); | |
2261 vv[0] += dx*(vl[j+1]-vh[j+1])/8; | |
2262 vv[j+1] = (vl[j+1]+vh[j+1])/2; | |
2263 P -= 1.5*dx*vv[j+1]; | |
2264 le += dx*dx; | |
2265 } | |
2266 for (j=0; j<d; j++) | |
2267 vv[j+1] += P*(evptx(fp,ih,j)-evptx(fp,il,j))/le; | |
2268 return(nc); | |
2269 } | |
2270 | |
2271 double triang_int(lf,x,what) | |
2272 lfit *lf; | |
2273 double *x; | |
2274 int what; | |
2275 { | |
2276 int d, i, j, k, vc, nc; | |
2277 int *ce, nce[1+MXDIM]; | |
2278 double xa[1+MXDIM], vv[(1+MXDIM)*(1+MXDIM)], lb; | |
2279 fitpt *fp; | |
2280 evstruc *evs; | |
2281 fp = &lf->fp; | |
2282 evs= &lf->evs; | |
2283 | |
2284 d = fp->d; vc = d+1; | |
2285 ce = evs->ce; | |
2286 i = 0; | |
2287 while ((i<evs->nce) && (!intri(x,&ce[i*vc],evp(fp),xa,d))) i++; | |
2288 if (i==evs->nce) return(NOSLN); | |
2289 i *= vc; | |
2290 for (j=0; j<vc; j++) nce[j] = ce[i+j]; | |
2291 triang_descend(lf,xa,nce); | |
2292 | |
2293 /* order the vertices -- needed for asymmetric interptr */ | |
2294 do | |
2295 { k=0; | |
2296 for (i=0; i<d; i++) | |
2297 if (nce[i]>nce[i+1]) | |
2298 { j=nce[i]; nce[i]=nce[i+1]; nce[i+1]=j; k=1; | |
2299 lb = xa[i]; xa[i] = xa[i+1]; xa[i+1] = lb; | |
2300 } | |
2301 } while(k); | |
2302 nc = 0; | |
2303 for (i=0; i<vc; i++) | |
2304 nc = triang_getvertexvals(fp,evs,&vv[i*nc],nce[i],what); | |
2305 return((d==2) ? triang_clotoch(evp(fp),vv,nce,nc,xa) : | |
2306 triang_cubicint(evp(fp),vv,nce,d,nc,xa)); | |
2307 } | |
2308 /* | |
2309 * Copyright 1996-2006 Catherine Loader. | |
2310 */ | |
2311 /* | |
2312 * Functions for computing residuals and fitted values from | |
2313 * the locfit object. | |
2314 * | |
2315 * fitted(lf,fit,what,cv,ty) computes fitted values from the | |
2316 * fit structure in lf. | |
2317 * resid(y,c,w,th,mi,ty) converts fitted values to residuals | |
2318 */ | |
2319 | |
2320 #include "lfev.h" | |
2321 | |
2322 #define NRT 8 | |
2323 static char *rtype[NRT] = { "deviance", "d2", "pearson", "raw", | |
2324 "ldot", "lddot", "fit", "mean" }; | |
2325 static int rvals[NRT] = { RDEV, RDEV2, RPEAR, RRAW, RLDOT, RLDDT, RFIT, RMEAN}; | |
2326 int restyp(z) | |
2327 char *z; | |
2328 { int val; | |
2329 | |
2330 val = pmatch(z, rtype, rvals, NRT, -1); | |
2331 if (val==-1) LERR(("Unknown type = %s",z)); | |
2332 return(val); | |
2333 } | |
2334 | |
2335 double resid(y,w,th,fam,ty,res) | |
2336 int fam, ty; | |
2337 double y, w, th, *res; | |
2338 { double raw; | |
2339 | |
2340 fam = fam & 63; | |
2341 if ((fam==TGAUS) | (fam==TROBT) | (fam==TCAUC)) | |
2342 raw = y-res[ZMEAN]; | |
2343 else | |
2344 raw = y-w*res[ZMEAN]; | |
2345 switch(ty) | |
2346 { case RDEV: | |
2347 if (res[ZDLL]>0) return(sqrt(-2*res[ZLIK])); | |
2348 else return(-sqrt(-2*res[ZLIK])); | |
2349 case RPEAR: | |
2350 if (res[ZDDLL]<=0) | |
2351 { if (res[ZDLL]==0) return(0); | |
2352 return(NOSLN); | |
2353 } | |
2354 return(res[ZDLL]/sqrt(res[ZDDLL])); | |
2355 case RRAW: return(raw); | |
2356 case RLDOT: return(res[ZDLL]); | |
2357 case RDEV2: return(-2*res[ZLIK]); | |
2358 case RLDDT: return(res[ZDDLL]); | |
2359 case RFIT: return(th); | |
2360 case RMEAN: return(res[ZMEAN]); | |
2361 default: LERR(("resid: unknown residual type %d",ty)); | |
2362 } | |
2363 return(0.0); | |
2364 } | |
2365 | |
2366 double studentize(res,inl,var,ty,link) | |
2367 double res, inl, var, *link; | |
2368 int ty; | |
2369 { double den; | |
2370 inl *= link[ZDDLL]; | |
2371 var = var*var*link[ZDDLL]; | |
2372 if (inl>1) inl = 1; | |
2373 if (var>inl) var = inl; | |
2374 den = 1-2*inl+var; | |
2375 if (den<0) return(0.0); | |
2376 switch(ty) | |
2377 { case RDEV: | |
2378 case RPEAR: | |
2379 case RRAW: | |
2380 case RLDOT: | |
2381 return(res/sqrt(den)); | |
2382 case RDEV2: | |
2383 return(res/den); | |
2384 default: return(res); | |
2385 } | |
2386 } | |
2387 | |
2388 void fitted(lf,fit,what,cv,st,ty) | |
2389 lfit *lf; | |
2390 double *fit; | |
2391 int what, cv, st, ty; | |
2392 { int i, j, d, n, evo; | |
2393 double xx[MXDIM], th, inl, var, link[LLEN]; | |
2394 n = lf->lfd.n; | |
2395 d = lf->lfd.d; | |
2396 evo = ev(&lf->evs); | |
2397 cv &= (evo!=ECROS); | |
2398 if ((evo==EDATA)|(evo==ECROS)) evo = EFITP; | |
2399 setfamily(&lf->sp); | |
2400 | |
2401 for (i=0; i<n; i++) | |
2402 { for (j=0; j<d; j++) xx[j] = datum(&lf->lfd,j,i); | |
2403 th = dointpoint(lf,xx,what,evo,i); | |
2404 if ((what==PT0)|(what==PVARI)) th = th*th; | |
2405 if (what==PCOEF) | |
2406 { | |
2407 th += base(&lf->lfd,i); | |
2408 stdlinks(link,&lf->lfd,&lf->sp,i,th,rsc(&lf->fp)); | |
2409 if ((cv)|(st)) | |
2410 { inl = dointpoint(lf,xx,PT0,evo,i); | |
2411 inl = inl*inl; | |
2412 if (cv) | |
2413 { th -= inl*link[ZDLL]; | |
2414 stdlinks(link,&lf->lfd,&lf->sp,i,th,rsc(&lf->fp)); | |
2415 } | |
2416 if (st) var = dointpoint(lf,xx,PNLX,evo,i); | |
2417 } | |
2418 fit[i] = resid(resp(&lf->lfd,i),prwt(&lf->lfd,i),th,fam(&lf->sp),ty,link); | |
2419 if (st) fit[i] = studentize(fit[i],inl,var,ty,link); | |
2420 } else fit[i] = th; | |
2421 if (lf_error) return; | |
2422 } | |
2423 } | |
2424 /* | |
2425 * Copyright 1996-2006 Catherine Loader. | |
2426 */ | |
2427 #include "lfev.h" | |
2428 | |
2429 extern double robscale; | |
2430 | |
2431 /* special version of ressumm to estimate sigma^2, with derivative estimation */ | |
2432 void ressummd(lf) | |
2433 lfit *lf; | |
2434 { int i; | |
2435 double s0, s1; | |
2436 s0 = s1 = 0.0; | |
2437 if ((fam(&lf->sp)&64)==0) | |
2438 { rv(&lf->fp) = 1.0; | |
2439 return; | |
2440 } | |
2441 for (i=0; i<lf->fp.nv; i++) | |
2442 { s0 += lf->fp.lik[2*lf->fp.nvm+i]; | |
2443 s1 += lf->fp.lik[i]; | |
2444 } | |
2445 if (s0==0.0) | |
2446 rv(&lf->fp) = 0.0; | |
2447 else | |
2448 rv(&lf->fp) = -2*s1/s0; | |
2449 } | |
2450 | |
2451 /* | |
2452 * res[0] = log-likelihood. | |
2453 * res[1] = df0 = tr(H) | |
2454 * res[2] = df0 = tr(H'H) | |
2455 * res[3] = s^2. | |
2456 * res[5] = robustscale. | |
2457 */ | |
2458 void ressumm(lf,des,res) | |
2459 lfit *lf; | |
2460 design *des; | |
2461 double *res; | |
2462 { int i, j, evo, tg; | |
2463 double *oy, pw, r1, r2, rdf, t0, t1, u[MXDIM], link[LLEN]; | |
2464 fitpt *fp; | |
2465 | |
2466 res[0] = res[1] = res[2] = 0.0; | |
2467 | |
2468 evo = ev(&lf->evs); | |
2469 if ((evo==EKDCE) | (evo==EPRES)) | |
2470 { res[3] = 1.0; | |
2471 return; | |
2472 } | |
2473 if (lf->dv.nd>0) | |
2474 { ressummd(lf); | |
2475 return; | |
2476 } | |
2477 | |
2478 r1 = r2 = 0.0; | |
2479 if ((evo==EDATA) | (evo==ECROS)) evo = EFITP; | |
2480 | |
2481 for (i=0; i<lf->lfd.n; i++) | |
2482 { for (j=0; j<lf->lfd.d; j++) u[j] = datum(&lf->lfd,j,i); | |
2483 fitv(des,i) = base(&lf->lfd,i)+dointpoint(lf,u,PCOEF,evo,i); | |
2484 des->wd[i] = resp(&(lf->lfd),i) - fitv(des,i); | |
2485 wght(des,i) = 1.0; | |
2486 des->ind[i] = i; | |
2487 } | |
2488 | |
2489 tg = fam(&lf->sp); | |
2490 res[5] = 1.0; | |
2491 if ((tg==TROBT+64) | (tg==TCAUC+64)) /* global robust scale */ | |
2492 { oy = lf->lfd.y; lf->lfd.y = des->wd; | |
2493 des->xev = lf->pc.xbar; | |
2494 locfit(&lf->lfd,des,&lf->sp,1,0,0); | |
2495 lf->lfd.y = oy; | |
2496 res[5] = robscale; | |
2497 } | |
2498 | |
2499 for (i=0; i<lf->lfd.n; i++) | |
2500 { for (j=0; j<lf->lfd.d; j++) u[j] = datum(&lf->lfd,j,i); | |
2501 t0 = dointpoint(lf,u,PT0,evo,i); | |
2502 t1 = dointpoint(lf,u,PNLX,evo,i); | |
2503 stdlinks(link,&lf->lfd,&lf->sp,i,fitv(des,i),res[5]); | |
2504 t1 = t1*t1*link[ZDDLL]; | |
2505 t0 = t0*t0*link[ZDDLL]; | |
2506 if (t1>1) t1 = 1; | |
2507 if (t0>1) t0 = 1; /* no observation gives >1 deg.free */ | |
2508 res[0] += link[ZLIK]; | |
2509 res[1] += t0; | |
2510 res[2] += t1; | |
2511 pw = prwt(&lf->lfd,i); | |
2512 if (pw>0) | |
2513 { r1 += link[ZDLL]*link[ZDLL]/pw; | |
2514 r2 += link[ZDDLL]/pw; | |
2515 } | |
2516 } | |
2517 | |
2518 res[3] = 1.0; | |
2519 if ((fam(&lf->sp)&64)==64) /* quasi family */ | |
2520 { rdf = lf->lfd.n-2*res[1]+res[2]; | |
2521 if (rdf<1.0) | |
2522 { WARN(("Estimated rdf < 1.0; not estimating variance")); | |
2523 } | |
2524 else | |
2525 res[3] = r1/r2 * lf->lfd.n / rdf; | |
2526 } | |
2527 | |
2528 /* try to ensure consistency for family="circ"! */ | |
2529 if (((fam(&lf->sp)&63)==TCIRC) & (lf->lfd.d==1)) | |
2530 { int *ind, nv; | |
2531 double dlt, th0, th1; | |
2532 ind = des->ind; | |
2533 nv = fp->nv; | |
2534 for (i=0; i<nv; i++) ind[i] = i; | |
2535 lforder(ind,evp(fp),0,nv-1); | |
2536 for (i=1; i<nv; i++) | |
2537 { dlt = evptx(fp,ind[i],0)-evptx(fp,ind[i-1],0); | |
2538 th0 = fp->coef[ind[i]]-dlt*fp->coef[ind[i]+nv]-fp->coef[ind[i-1]]; | |
2539 th1 = fp->coef[ind[i]]-dlt*fp->coef[ind[i-1]+nv]-fp->coef[ind[i-1]]; | |
2540 if ((th0>PI)&(th1>PI)) | |
2541 { for (j=0; j<i; j++) | |
2542 fp->coef[ind[j]] += 2*PI; | |
2543 i--; | |
2544 } | |
2545 if ((th0<(-PI))&(th1<(-PI))) | |
2546 { for (j=0; j<i; j++) | |
2547 fp->coef[ind[j]] -= 2*PI; | |
2548 i--; | |
2549 } | |
2550 } | |
2551 } | |
2552 | |
2553 } | |
2554 | |
2555 double rss(lf,des,df) | |
2556 lfit *lf; | |
2557 design *des; | |
2558 double *df; | |
2559 { double ss, res[10]; | |
2560 ss = 0; | |
2561 ressumm(lf,des,res); | |
2562 *df = lf->lfd.n - 2*res[1] + res[2]; | |
2563 return(-2*res[0]); | |
2564 } | |
2565 /* | |
2566 * Copyright 1996-2006 Catherine Loader. | |
2567 */ | |
2568 /* | |
2569 * | |
2570 * Derivative corrections. The local slopes are not the derivatives | |
2571 * of the local likelihood estimate; the function dercor() computes | |
2572 * the adjustment to get the correct derivatives under the assumption | |
2573 * that h is constant. | |
2574 * | |
2575 * By differentiating the local likelihood equations, one obtains | |
2576 * | |
2577 * d ^ ^ T -1 T d . ^ | |
2578 * -- a = a - (X W V X) X -- W l( Y, X a) | |
2579 * dx 0 1 dx | |
2580 */ | |
2581 | |
2582 #include "lfev.h" | |
2583 extern double robscale; | |
2584 | |
2585 void dercor(lfd,sp,des,coef) | |
2586 lfdata *lfd; | |
2587 smpar *sp; | |
2588 design *des; | |
2589 double *coef; | |
2590 { double s1, dc[MXDIM], wd, link[LLEN]; | |
2591 int i, ii, j, m, d, p; | |
2592 if (fam(sp)<=THAZ) return; | |
2593 if (ker(sp)==WPARM) return; | |
2594 | |
2595 d = lfd->d; | |
2596 p = des->p; m = des->n; | |
2597 | |
2598 if (lf_debug>1) mut_printf(" Correcting derivatives\n"); | |
2599 fitfun(lfd, sp, des->xev,des->xev,des->f1,NULL); | |
2600 jacob_solve(&des->xtwx,des->f1); | |
2601 setzero(dc,d); | |
2602 | |
2603 /* correction term is e1^T (XTWVX)^{-1} XTW' ldot. */ | |
2604 for (i=0; i<m; i++) | |
2605 { s1 = innerprod(des->f1,d_xi(des,i),p); | |
2606 ii = des->ind[i]; | |
2607 stdlinks(link,lfd,sp,ii,fitv(des,ii),robscale); | |
2608 for (j=0; j<d; j++) | |
2609 { wd = wght(des,ii)*weightd(datum(lfd,j,ii)-des->xev[j],lfd->sca[j], | |
2610 d,ker(sp),kt(sp),des->h,lfd->sty[j],dist(des,ii)); | |
2611 dc[j] += s1*wd*link[ZDLL]; | |
2612 } | |
2613 | |
2614 } | |
2615 for (j=0; j<d; j++) coef[j+1] += dc[j]; | |
2616 } | |
2617 /* | |
2618 * Copyright 1996-2006 Catherine Loader. | |
2619 */ | |
2620 #include "lfev.h" | |
2621 | |
2622 void allocallcf(lf) | |
2623 lfit *lf; | |
2624 { lf->fp.coef = VVEC(lf,0); | |
2625 lf->fp.h = VVEC(lf,NPAR(lf)); | |
2626 } | |
2627 | |
2628 int procvallcf(des,lf,v) | |
2629 design *des; | |
2630 lfit *lf; | |
2631 int v; | |
2632 { int i, p, lf_status; | |
2633 | |
2634 lf_status = procv_nov(des,lf,v); | |
2635 if (lf_error) return(lf_status); | |
2636 | |
2637 p = NPAR(lf); | |
2638 for (i=0; i<p; i++) VVAL(lf,v,i) = des->cf[i]; | |
2639 lf->fp.h[v] = des->h; | |
2640 | |
2641 return(0); | |
2642 } | |
2643 | |
2644 void initallcf(lf) | |
2645 lfit *lf; | |
2646 { PROCV(lf) = procvallcf; | |
2647 ALLOC(lf) = allocallcf; | |
2648 PPROC(lf) = NULL; | |
2649 KEEPV(lf) = NPAR(lf)+1; | |
2650 KEEPC(lf) = 0; | |
2651 NOPC(lf) = 1; | |
2652 } | |
2653 /* | |
2654 * Copyright 1996-2006 Catherine Loader. | |
2655 */ | |
2656 #include "lfev.h" | |
2657 | |
2658 void pprocgam(lf,des,res) | |
2659 lfit *lf; | |
2660 design *des; | |
2661 double *res; | |
2662 { int i, j, n, evo, op; | |
2663 double *fv, *vr, df, t0, t1, u[MXDIM], link[LLEN]; | |
2664 | |
2665 n = lf->lfd.n; | |
2666 fv = res; | |
2667 vr = &res[n]; | |
2668 df = 0.0; | |
2669 | |
2670 evo = ev(&lf->evs); | |
2671 if (evo==EDATA) evo = EFITP; | |
2672 | |
2673 for (i=0; i<n; i++) | |
2674 { for (j=0; j<lf->lfd.d; j++) u[j] = datum(&lf->lfd,j,i); | |
2675 fitv(des,i) = base(&lf->lfd,i)+dointpoint(lf,u,PCOEF,evo,i); | |
2676 lf->lfd.y[i] -= fitv(des,i); | |
2677 wght(des,i) = 1.0; | |
2678 des->ind[i] = i; | |
2679 | |
2680 t0 = dointpoint(lf,u,PT0,evo,i); | |
2681 t1 = dointpoint(lf,u,PNLX,evo,i); | |
2682 stdlinks(link,&lf->lfd,&lf->sp,i,fitv(des,i),1.0); | |
2683 t0 = t0*t0*link[ZDDLL]; | |
2684 t1 = t1*t1*link[ZDDLL]; | |
2685 if (t0>1) t0 = 1; /* no observation gives >1 deg.free */ | |
2686 if (t1>1) t1 = 1; /* no observation gives >1 deg.free */ | |
2687 vr[i] = t1; | |
2688 df += t0; | |
2689 } | |
2690 | |
2691 des->n = n; | |
2692 deg(&lf->sp) = 1; | |
2693 op = npar(&lf->sp); | |
2694 npar(&lf->sp) = des->p = 1+lf->lfd.d; | |
2695 des->xev = lf->pc.xbar; | |
2696 locfit(&lf->lfd,des,&lf->sp,1,0,0); | |
2697 | |
2698 for (i=0; i<n; i++) fv[i] = resp(&lf->lfd,i) - fitv(des,i); | |
2699 for (i=0; i<=lf->lfd.d; i++) | |
2700 lf->pc.coef[i] += des->cf[i]; | |
2701 res[2*n] = df-2; | |
2702 npar(&lf->sp) = op; | |
2703 } | |
2704 | |
2705 void initgam(lf) | |
2706 lfit *lf; | |
2707 { initstd(lf); | |
2708 PPROC(lf) = pprocgam; | |
2709 KEEPC(lf) = 2*NOBS(lf)+1; | |
2710 } | |
2711 /* | |
2712 * Copyright 1996-2006 Catherine Loader. | |
2713 */ | |
2714 #include "lfev.h" | |
2715 | |
2716 int procvhatm(des,lf,v) | |
2717 design *des; | |
2718 lfit *lf; | |
2719 int v; | |
2720 { int k; | |
2721 double *l; | |
2722 l = &lf->fp.coef[v*lf->lfd.n]; | |
2723 if ((ker(&lf->sp)!=WPARM) | (!haspc(&lf->pc))) | |
2724 { k = procv_nov(des,lf,v); | |
2725 wdiag(&lf->lfd,&lf->sp,des,l,&lf->dv,0,1,1); | |
2726 } | |
2727 else | |
2728 wdiagp(&lf->lfd,&lf->sp,des,l,&lf->pc,&lf->dv,0,1,1); | |
2729 lf->fp.h[v] = des->h; | |
2730 return(k); | |
2731 } | |
2732 | |
2733 void allochatm(lf) | |
2734 lfit *lf; | |
2735 { lf->fp.coef = VVEC(lf,0); | |
2736 lf->fp.h = VVEC(lf,NOBS(lf)); | |
2737 } | |
2738 | |
2739 void pprochatm(lf,des,res) | |
2740 lfit *lf; | |
2741 design *des; | |
2742 double *res; | |
2743 { transpose(lf->fp.coef,lf->fp.nvm,lf->lfd.n); | |
2744 } | |
2745 | |
2746 void inithatm(lf) | |
2747 lfit *lf; | |
2748 { PROCV(lf) = procvhatm; | |
2749 ALLOC(lf) = allochatm; | |
2750 PPROC(lf) = pprochatm; | |
2751 KEEPV(lf) = NOBS(lf)+1; | |
2752 KEEPC(lf) = 1; | |
2753 NOPC(lf) = 1; /* could use pc if mi[MKER] == WPARM */ | |
2754 } | |
2755 /* | |
2756 * Copyright 1996-2006 Catherine Loader. | |
2757 */ | |
2758 #include "lfev.h" | |
2759 | |
2760 static lfit *lf_scb; | |
2761 static lfdata *lfd_scb; | |
2762 static smpar *scb_sp; | |
2763 static design *des_scb; | |
2764 | |
2765 int scbfitter(x,l,reqd) | |
2766 double *x, *l; | |
2767 int reqd; | |
2768 { | |
2769 int m; | |
2770 des_scb->xev = x; | |
2771 if ((ker(scb_sp)!=WPARM) | (!haspc(&lf_scb->pc))) | |
2772 { locfit(lfd_scb,des_scb,&lf_scb->sp,1,1,0); | |
2773 m = wdiag(lfd_scb, scb_sp, des_scb,l,&lf_scb->dv,reqd,2,0); | |
2774 } | |
2775 else | |
2776 m = wdiagp(lfd_scb, scb_sp, des_scb,l,&lf_scb->pc,&lf_scb->dv,reqd,2,0); | |
2777 return(m); | |
2778 } | |
2779 | |
2780 int constants(lf,des,res) | |
2781 lfit *lf; | |
2782 design *des; | |
2783 double *res; | |
2784 { | |
2785 int d, m, nt; | |
2786 double *wk; | |
2787 evstruc *evs; | |
2788 | |
2789 lf_scb = lf; | |
2790 des_scb = des; | |
2791 lfd_scb = &lf->lfd; | |
2792 scb_sp = &lf->sp; | |
2793 | |
2794 evs = &lf->evs; | |
2795 d = lfd_scb->d; | |
2796 m = lfd_scb->n; | |
2797 trchck(lf,0,0,0); | |
2798 | |
2799 if (lf_error) return(0); | |
2800 if ((ker(scb_sp) != WPARM) && (lf->sp.nn>0)) | |
2801 WARN(("constants are approximate for varying h")); | |
2802 npar(scb_sp) = calcp(scb_sp,lf->lfd.d); | |
2803 des_init(des,m,npar(scb_sp)); | |
2804 set_scales(&lf->lfd); | |
2805 set_flim(&lf->lfd,&lf->evs); | |
2806 compparcomp(des,&lf->lfd,&lf->sp,&lf->pc,ker(scb_sp)!=WPARM); | |
2807 | |
2808 wk = &res[d+1]; | |
2809 nt = tube_constants(scbfitter,d,m,ev(evs),mg(evs),evs->fl, | |
2810 res,wk,(d>3) ? 4 : d+1,0); | |
2811 lf->evs.nce = nt; /* cheat way to return it to S. */ | |
2812 return(nt); | |
2813 } | |
2814 | |
2815 void initkappa(lf) | |
2816 lfit *lf; | |
2817 { PROCV(lf) = NULL; | |
2818 ALLOC(lf) = NULL; | |
2819 PPROC(lf) = (void *)constants; | |
2820 KEEPV(lf) = 0; | |
2821 KEEPC(lf) = NVAR(lf)+1+k0_reqd(NVAR(lf),NOBS(lf),0); | |
2822 NOPC(lf) = 0; | |
2823 } | |
2824 /* | |
2825 * Copyright 1996-2006 Catherine Loader. | |
2826 */ | |
2827 #include "lfev.h" | |
2828 | |
2829 /* fix df computation for link=IDENT. */ | |
2830 void pproclscv(lf,des,res) | |
2831 lfit *lf; | |
2832 design *des; | |
2833 double *res; | |
2834 { double df, fh, fh_cv, infl, z0, z1, x[MXDIM]; | |
2835 int i, n, j, evo; | |
2836 z1 = df = 0.0; | |
2837 evo = ev(&lf->evs); | |
2838 n = lf->lfd.n; | |
2839 if ((evo==EDATA) | (evo==ECROS)) evo = EFITP; | |
2840 | |
2841 z0 = dens_integrate(lf,des,2); | |
2842 | |
2843 for (i=0; i<n; i++) | |
2844 { for (j=0; j<lf->lfd.d; j++) x[j] = datum(&lf->lfd,j,i); | |
2845 fh = base(&lf->lfd,i)+dointpoint(lf,x,PCOEF,evo,i); | |
2846 if (link(&lf->sp)==LLOG) fh = exp(fh); | |
2847 infl = dointpoint(lf,x,PT0,evo,i); | |
2848 infl = infl * infl; | |
2849 if (infl>1) infl = 1; | |
2850 fh_cv = (link(&lf->sp) == LIDENT) ? | |
2851 (n*fh - infl) / (n-1.0) : fh*(1-infl)*n/(n-1.0); | |
2852 z1 += fh_cv; | |
2853 df += infl; | |
2854 } | |
2855 | |
2856 res[0] = z0-2*z1/n; | |
2857 res[1] = df; | |
2858 } | |
2859 | |
2860 void initlscv(lf) | |
2861 lfit *lf; | |
2862 { initstd(lf); | |
2863 KEEPC(lf) = 2; | |
2864 PPROC(lf) = pproclscv; | |
2865 NOPC(lf) = 1; | |
2866 } | |
2867 /* | |
2868 * Copyright 1996-2006 Catherine Loader. | |
2869 */ | |
2870 #include "lfev.h" | |
2871 | |
2872 static double pen, sig2; | |
2873 | |
2874 void goldensec(f,des,tr,eps,xm,ym,meth) | |
2875 double (*f)(), eps, *xm, *ym; | |
2876 int meth; | |
2877 design *des; | |
2878 lfit *tr; | |
2879 { double x[4], y[4], xx[11], yy[11]; | |
2880 int i, im; | |
2881 xx[0] = tr->sp.fixh; | |
2882 if (xx[0]<=0) | |
2883 { LERR(("regband: initialize h>0")); | |
2884 return; | |
2885 } | |
2886 for (i=0; i<=10; i++) | |
2887 { if (i>0) xx[i] = (1+gold_rat)*xx[i-1]; | |
2888 yy[i] = f(xx[i],des,tr,meth); | |
2889 if ((i==0) || (yy[i]<yy[im])) im = i; | |
2890 } | |
2891 if (im==0) im = 1; | |
2892 if (im==10)im = 9; | |
2893 x[0] = xx[im-1]; y[0] = yy[im-1]; | |
2894 x[1] = xx[im]; y[1] = yy[im]; | |
2895 x[3] = xx[im+1]; y[3] = yy[im+1]; | |
2896 x[2] = gold_rat*x[3]+(1-gold_rat)*x[0]; | |
2897 y[2] = f(x[2],des,tr,meth); | |
2898 while (x[3]-x[0]>eps) | |
2899 { if (y[1]<y[2]) | |
2900 { x[3] = x[2]; y[3] = y[2]; | |
2901 x[2] = x[1]; y[2] = y[1]; | |
2902 x[1] = gold_rat*x[0]+(1-gold_rat)*x[3]; | |
2903 y[1] = f(x[1],des,tr,meth); | |
2904 } | |
2905 else | |
2906 { x[0] = x[1]; y[0] = y[1]; | |
2907 x[1] = x[2]; y[1] = y[2]; | |
2908 x[2] = gold_rat*x[3]+(1-gold_rat)*x[0]; | |
2909 y[2] = f(x[2],des,tr,meth); | |
2910 } | |
2911 } | |
2912 im = 0; | |
2913 for (i=1; i<4; i++) if (y[i]<y[im]) im = i; | |
2914 *xm = x[im]; *ym = y[im]; | |
2915 } | |
2916 | |
2917 double dnk(x,k) | |
2918 double x; | |
2919 int k; | |
2920 { double f; | |
2921 switch(k) | |
2922 { case 0: f = 1; break; | |
2923 case 1: f = -x; break; | |
2924 case 2: f = x*x-1; break; | |
2925 case 3: f = x*(x*x-3); break; | |
2926 case 4: f = 3-x*x*(6-x*x); break; | |
2927 case 5: f = -x*(15-x*x*(10-x*x)); break; | |
2928 case 6: f = -15+x*x*(45-x*x*(15-x*x)); break; | |
2929 default: LERR(("dnk: k=%d too large",k)); return(0.0); | |
2930 } | |
2931 return(f*exp(-x*x/2)/S2PI); | |
2932 } | |
2933 | |
2934 double locai(h,des,lf) | |
2935 double h; | |
2936 design *des; | |
2937 lfit *lf; | |
2938 { double cp, res[10]; | |
2939 nn(&lf->sp) = h; | |
2940 lf->mdl.procv = procvstd; | |
2941 nstartlf(des,lf); | |
2942 ressumm(lf,des,res); | |
2943 cp = -2*res[0] + pen*res[1]; | |
2944 return(cp); | |
2945 } | |
2946 | |
2947 static int fc; | |
2948 | |
2949 double loccp(h,des,lf,m) /* m=1: cp m=2: gcv */ | |
2950 double h; | |
2951 design *des; | |
2952 lfit *lf; | |
2953 int m; | |
2954 { double cp, res[10]; | |
2955 int dg, n; | |
2956 | |
2957 n = lf->lfd.n; | |
2958 nn(&lf->sp) = 0; | |
2959 fixh(&lf->sp) = h; | |
2960 lf->mdl.procv = procvstd; | |
2961 nstartlf(des,lf); | |
2962 ressumm(lf,des,res); | |
2963 if (m==1) | |
2964 { if (fc) sig2 = res[3]; /* first call - set sig2 */ | |
2965 cp = -2*res[0]/sig2 - n + 2*res[1]; | |
2966 } | |
2967 else | |
2968 cp = -2*n*res[0]/((n-res[1])*(n-res[1])); | |
2969 fc = 0; | |
2970 return(cp); | |
2971 } | |
2972 | |
2973 double cp(des,lf,meth) | |
2974 design *des; | |
2975 lfit *lf; | |
2976 int meth; | |
2977 { double hm, ym; | |
2978 fc = 1; | |
2979 goldensec(loccp,des,lf,0.001,&hm,&ym,meth); | |
2980 return(hm); | |
2981 } | |
2982 | |
2983 double gkk(des,lf) | |
2984 design *des; | |
2985 lfit *lf; | |
2986 { double h, h5, nf, th; | |
2987 int i, j, n, dg0, dg1; | |
2988 ev(&lf->evs)= EDATA; | |
2989 nn(&lf->sp) = 0; | |
2990 n = lf->lfd.n; | |
2991 dg0 = deg0(&lf->sp); /* target degree */ | |
2992 dg1 = dg0+1+(dg0%2==0); /* pilot degree */ | |
2993 nf = exp(log(1.0*n)/10); /* bandwidth inflation factor */ | |
2994 h = lf->sp.fixh; /* start bandwidth */ | |
2995 for (i=0; i<=10; i++) | |
2996 { deg(&lf->sp) = dg1; | |
2997 lf->sp.fixh = h*nf; | |
2998 lf->mdl.procv = procvstd; | |
2999 nstartlf(des,lf); | |
3000 th = 0; | |
3001 for (j=10; j<n-10; j++) | |
3002 th += lf->fp.coef[dg1*n+j]*lf->fp.coef[dg1*n+j]; | |
3003 th *= n/(n-20.0); | |
3004 h5 = sig2 * Wikk(ker(&lf->sp),dg0) / th; | |
3005 h = exp(log(h5)/(2*dg1+1)); | |
3006 if (lf_error) return(0.0); | |
3007 /* mut_printf("pilot %8.5f sel %8.5f\n",lf->sp.fixh,h); */ | |
3008 } | |
3009 return(h); | |
3010 } | |
3011 | |
3012 double rsw(des,lf) | |
3013 design *des; | |
3014 lfit *lf; | |
3015 { int i, j, k, nmax, nvm, n, mk, evo, dg0, dg1; | |
3016 double rss[6], cp[6], th22, dx, d2, hh; | |
3017 nmax = 5; | |
3018 evo = ev(&lf->evs); ev(&lf->evs) = EGRID; | |
3019 mk = ker(&lf->sp); ker(&lf->sp) = WRECT; | |
3020 dg0 = deg0(&lf->sp); | |
3021 dg1 = 1 + dg0 + (dg0%2==0); | |
3022 deg(&lf->sp) = 4; | |
3023 for (k=nmax; k>0; k--) | |
3024 { lf->evs.mg[0] = k; | |
3025 lf->evs.fl[0] = 1.0/(2*k); | |
3026 lf->evs.fl[1] = 1-1.0/(2*k); | |
3027 nn(&lf->sp) = 0; | |
3028 fixh(&lf->sp) = 1.0/(2*k); | |
3029 lf->mdl.procv = procvstd; | |
3030 nstartlf(des,lf); | |
3031 nvm = lf->fp.nvm; | |
3032 rss[k] = 0; | |
3033 for (i=0; i<k; i++) rss[k] += -2*lf->fp.lik[i]; | |
3034 } | |
3035 n = lf->lfd.n; k = 1; | |
3036 for (i=1; i<=nmax; i++) | |
3037 { /* cp[i] = (n-5*nmax)*rss[i]/rss[nmax]-(n-10*i); */ | |
3038 cp[i] = rss[i]/sig2-(n-10*i); | |
3039 if (cp[i]<cp[k]) k = i; | |
3040 } | |
3041 lf->evs.mg[0] = k; | |
3042 lf->evs.fl[0] = 1.0/(2*k); | |
3043 lf->evs.fl[1] = 1-1.0/(2*k); | |
3044 nn(&lf->sp) = 0; | |
3045 fixh(&lf->sp) = 1.0/(2*k); | |
3046 lf->mdl.procv = procvstd; | |
3047 nstartlf(des,lf); | |
3048 ker(&lf->sp) = mk; ev(&lf->evs) = evo; | |
3049 nvm = lf->fp.nvm; | |
3050 th22 = 0; | |
3051 for (i=10; i<n-10; i++) | |
3052 { j = floor(k*datum(&lf->lfd,0,i)); | |
3053 if (j>=k) j = k-1; | |
3054 dx = datum(&lf->lfd,0,i)-evptx(&lf->fp,0,j); | |
3055 if (dg1==2) | |
3056 d2 = lf->fp.coef[2*nvm+j]+dx*lf->fp.coef[3*nvm+j]+dx*dx*lf->fp.coef[4*nvm+j]/2; | |
3057 else d2 = lf->fp.coef[4*nvm+j]; | |
3058 th22 += d2*d2; | |
3059 } | |
3060 hh = Wikk(mk,dg0)*sig2/th22*(n-20.0)/n; | |
3061 return(exp(log(hh)/(2*dg1+1))); | |
3062 } | |
3063 | |
3064 #define MAXMETH 10 | |
3065 | |
3066 void rband(lf,des,hhat) | |
3067 lfit *lf; | |
3068 design *des; | |
3069 double *hhat; | |
3070 { int i, dg, nmeth, meth[MAXMETH]; | |
3071 double h0, res[10]; | |
3072 | |
3073 nmeth = lf->dv.nd; | |
3074 for (i=0; i<nmeth; i++) meth[i] = lf->dv.deriv[i]; | |
3075 lf->dv.nd = 0; | |
3076 | |
3077 /* first, estimate sigma^2. | |
3078 * this is ridiculously bad. lf->sp.fixh = 0.05???? | |
3079 */ | |
3080 /* dg = deg(&lf->sp); deg(&lf->sp) = 2; | |
3081 h0 = lf->sp.fixh; lf->sp.fixh = 0.05; | |
3082 lf->mdl.procv = procvstd; | |
3083 nstartlf(des,lf); | |
3084 ressumm(lf,des,res); | |
3085 deg(&lf->sp) = dg; lf->sp.fixh = h0; | |
3086 sig2 = res[3]; */ | |
3087 | |
3088 for (i=0; i<nmeth; i++) | |
3089 { | |
3090 switch(meth[i]) | |
3091 { case 0: hhat[i] = cp(des,lf,1); | |
3092 break; | |
3093 case 1: hhat[i] = cp(des,lf,2); | |
3094 break; | |
3095 case 2: hhat[i] = gkk(des,lf); | |
3096 break; | |
3097 case 3: hhat[i] = rsw(des,lf); | |
3098 break; | |
3099 default: hhat[i] = 0; | |
3100 mut_printf("Unknown method %d\n",meth[i]); | |
3101 } | |
3102 if (lf_error) i = nmeth; | |
3103 } | |
3104 lf->dv.nd = nmeth; | |
3105 } | |
3106 | |
3107 void initrband(lf) | |
3108 lfit *lf; | |
3109 { | |
3110 initstd(lf); | |
3111 KEEPC(lf) = MAXMETH; | |
3112 PROCV(lf) = NULL; | |
3113 PPROC(lf) = rband; | |
3114 } | |
3115 /* | |
3116 * Copyright 1996-2006 Catherine Loader. | |
3117 */ | |
3118 #include "lfev.h" | |
3119 static double scb_crit, *x, c[10], kap[5], kaq[5], max_p2; | |
3120 static int side, type; | |
3121 design *scb_des; | |
3122 | |
3123 double covar_par(lf,des,x1,x2) | |
3124 lfit *lf; | |
3125 design *des; | |
3126 double x1, x2; | |
3127 { double *v1, *v2, *wk; | |
3128 paramcomp *pc; | |
3129 int i, j, p, ispar; | |
3130 | |
3131 v1 = des->f1; v2 = des->ss; wk = des->oc; | |
3132 ispar = (ker(&lf->sp)==WPARM) && (haspc(&lf->pc)); | |
3133 p = npar(&lf->sp); | |
3134 | |
3135 /* for parametric models, the covariance is | |
3136 * A(x1)^T (X^T W V X)^{-1} A(x2) | |
3137 * which we can find easily from the parametric component. | |
3138 */ | |
3139 if (ispar) | |
3140 { pc = &lf->pc; | |
3141 fitfun(&lf->lfd, &lf->sp, &x1,pc->xbar,v1,NULL); | |
3142 fitfun(&lf->lfd, &lf->sp, &x2,pc->xbar,v2,NULL); | |
3143 jacob_hsolve(&lf->pc.xtwx,v1); | |
3144 jacob_hsolve(&lf->pc.xtwx,v2); | |
3145 } | |
3146 | |
3147 /* for non-parametric models, we must use the cholseky decomposition | |
3148 * of M2 = X^T W^2 V X. Courtesy of lf_vcov caclulations, should have | |
3149 * des->P = M2^{1/2} M1^{-1}. | |
3150 */ | |
3151 if (!ispar) | |
3152 { fitfun(&lf->lfd, &lf->sp, &x1,des->xev,wk,NULL); | |
3153 for (i=0; i<p; i++) | |
3154 { v1[i] = 0; | |
3155 for (j=0; j<p; j++) v1[i] += des->P[i*p+j]*wk[j]; | |
3156 } | |
3157 fitfun(&lf->lfd, &lf->sp, &x2,des->xev,wk,NULL); | |
3158 for (i=0; i<p; i++) | |
3159 { v2[i] = 0; | |
3160 for (j=0; j<p; j++) v2[i] += des->P[i*p+j]*wk[j]; | |
3161 } | |
3162 } | |
3163 | |
3164 return(innerprod(v1,v2,p)); | |
3165 } | |
3166 | |
3167 void cumulant(lf,des,sd) | |
3168 lfit *lf; | |
3169 design *des; | |
3170 double sd; | |
3171 { double b2i, b3i, b3j, b4i; | |
3172 double ss, si, sj, uii, uij, ujj, k1; | |
3173 int ii, i, j, jj; | |
3174 for (i=1; i<10; i++) c[i] = 0.0; | |
3175 k1 = 0; | |
3176 | |
3177 /* ss = sd*sd; */ | |
3178 ss = covar_par(lf,des,des->xev[0],des->xev[0]); | |
3179 | |
3180 /* | |
3181 * this isn't valid for nonparametric models. At a minimum, | |
3182 * the sums would have to include weights. Still have to work | |
3183 * out the right way. | |
3184 */ | |
3185 for (i=0; i<lf->lfd.n; i++) | |
3186 { ii = des->ind[i]; | |
3187 b2i = b2(fitv(des,ii),fam(&lf->sp),prwt(&lf->lfd,ii)); | |
3188 b3i = b3(fitv(des,ii),fam(&lf->sp),prwt(&lf->lfd,ii)); | |
3189 b4i = b4(fitv(des,ii),fam(&lf->sp),prwt(&lf->lfd,ii)); | |
3190 si = covar_par(lf,des,des->xev[0],datum(&lf->lfd,0,ii)); | |
3191 uii= covar_par(lf,des,datum(&lf->lfd,0,ii),datum(&lf->lfd,0,ii)); | |
3192 if (lf_error) return; | |
3193 | |
3194 c[2] += b4i*si*si*uii; | |
3195 c[6] += b4i*si*si*si*si; | |
3196 c[7] += b3i*si*uii; | |
3197 c[8] += b3i*si*si*si; | |
3198 /* c[9] += b2i*si*si*si*si; | |
3199 c[9] += b2i*b2i*si*si*si*si; */ | |
3200 k1 += b3i*si*(si*si/ss-uii); | |
3201 | |
3202 /* i=j components */ | |
3203 c[1] += b3i*b3i*si*si*uii*uii; | |
3204 c[3] += b3i*b3i*si*si*si*si*uii; | |
3205 c[4] += b3i*b3i*si*si*uii*uii; | |
3206 | |
3207 for (j=i+1; j<lf->lfd.n; j++) | |
3208 { jj = des->ind[j]; | |
3209 b3j = b3(fitv(des,ii),fam(&lf->sp),prwt(&lf->lfd,jj)); | |
3210 sj = covar_par(lf,des,des->xev[0],datum(&lf->lfd,0,jj)); | |
3211 uij= covar_par(lf,des,datum(&lf->lfd,0,ii),datum(&lf->lfd,0,jj)); | |
3212 ujj= covar_par(lf,des,datum(&lf->lfd,0,jj),datum(&lf->lfd,0,jj)); | |
3213 | |
3214 c[1] += 2*b3i*b3j*si*sj*uij*uij; | |
3215 c[3] += 2*b3i*b3j*si*si*sj*sj*uij; | |
3216 c[4] += b3i*b3j*uij*(si*si*ujj+sj*sj*uii); | |
3217 if (lf_error) return; | |
3218 } | |
3219 } | |
3220 c[5] = c[1]; | |
3221 c[7] = c[7]*c[8]; | |
3222 c[8] = c[8]*c[8]; | |
3223 | |
3224 c[1] /= ss; c[2] /= ss; c[3] /= ss*ss; c[4] /= ss; | |
3225 c[5] /= ss; c[6] /= ss*ss; c[7] /= ss*ss; | |
3226 c[8] /= ss*ss*ss; c[9] /= ss*ss; | |
3227 | |
3228 /* constants used in p(x,z) computation */ | |
3229 kap[1] = k1/(2*sqrt(ss)); | |
3230 kap[2] = 1 + 0.5*(c[1]-c[2]+c[4]-c[7]) - 3*c[3] + c[6] + 1.75*c[8]; | |
3231 kap[4] = -9*c[3] + 3*c[6] + 6*c[8] + 3*c[9]; | |
3232 | |
3233 /* constants used in q(x,u) computation */ | |
3234 kaq[2] = c[3] - 1.5*c[8] - c[5] - c[4] + 0.5*c[7] + c[6] - c[2]; | |
3235 kaq[4] = -3*c[3] - 6*c[4] - 6*c[5] + 3*c[6] + 3*c[7] - 3*c[8] + 3*c[9]; | |
3236 } | |
3237 | |
3238 /* q2(u) := u+q2(x,u) in paper */ | |
3239 double q2(u) | |
3240 double u; | |
3241 { return(u-u*(36.0*kaq[2] + 3*kaq[4]*(u*u-3) + c[8]*((u*u-10)*u*u+15))/72.0); | |
3242 } | |
3243 | |
3244 /* p2(u) := p2(x,u) in paper */ | |
3245 double p2(u) | |
3246 double u; | |
3247 { return( -u*( 36*(kap[2]-1+kap[1]*kap[1]) | |
3248 + 3*(kap[4]+4*kap[1]*sqrt(kap[3]))*(u*u-3) | |
3249 + c[8]*((u*u-10)*u*u+15) ) / 72 ); | |
3250 } | |
3251 | |
3252 extern int likereg(); | |
3253 double gldn_like(a) | |
3254 double a; | |
3255 { int err; | |
3256 | |
3257 scb_des->fix[0] = 1; | |
3258 scb_des->cf[0] = a; | |
3259 max_nr(likereg, scb_des->cf, scb_des->oc, scb_des->res, scb_des->f1, | |
3260 &scb_des->xtwx, scb_des->p, lf_maxit, 1.0e-6, &err); | |
3261 scb_des->fix[0] = 0; | |
3262 | |
3263 return(scb_des->llk); | |
3264 } | |
3265 | |
3266 /* v1/v2 is correct for deg=0 only */ | |
3267 void get_gldn(fp,des,lo,hi,v) | |
3268 fitpt *fp; | |
3269 design *des; | |
3270 double *lo, *hi; | |
3271 int v; | |
3272 { double v1, v2, c, tlk; | |
3273 int err; | |
3274 | |
3275 v1 = fp->nlx[v]; | |
3276 v2 = fp->t0[v]; | |
3277 c = scb_crit * v1 / v2; | |
3278 tlk = des->llk - c*c/2; | |
3279 mut_printf("v %8.5f %8.5f c %8.5f tlk %8.5f llk %8.5f\n",v1,v2,c,tlk,des->llk); | |
3280 | |
3281 /* want: { a : l(a) >= l(a-hat) - c*c/2 } */ | |
3282 lo[v] = fp->coef[v] - scb_crit*v1; | |
3283 hi[v] = fp->coef[v] + scb_crit*v1; | |
3284 | |
3285 err = 0; | |
3286 | |
3287 mut_printf("lo %2d\n",v); | |
3288 lo[v] = solve_secant(gldn_like,tlk,lo[v],fp->coef[v],1e-8,BDF_EXPLEFT,&err); | |
3289 if (err>0) mut_printf("solve_secant error\n"); | |
3290 mut_printf("hi %2d\n",v); | |
3291 hi[v] = solve_secant(gldn_like,tlk,fp->coef[v],hi[v],1e-8,BDF_EXPRIGHT,&err); | |
3292 if (err>0) mut_printf("solve_secant error\n"); | |
3293 } | |
3294 | |
3295 int procvscb2(des,lf,v) | |
3296 design *des; | |
3297 lfit *lf; | |
3298 int v; | |
3299 { double thhat, sd, *lo, *hi, u; | |
3300 int err, st, tmp; | |
3301 x = des->xev = evpt(&lf->fp,v); | |
3302 tmp = haspc(&lf->pc); | |
3303 /* if ((ker(&lf->sp)==WPARM) && (haspc(&lf->pc))) | |
3304 { lf->coef[v] = thhat = addparcomp(lf,des->xev,PCOEF); | |
3305 lf->nlx[v] = lf->t0[v] = sd = addparcomp(lf,des->xev,PNLX); | |
3306 } | |
3307 else */ | |
3308 { haspc(&lf->pc) = 0; | |
3309 st = procvstd(des,lf,v); | |
3310 thhat = lf->fp.coef[v]; | |
3311 sd = lf->fp.nlx[v]; | |
3312 } | |
3313 if ((type==GLM2) | (type==GLM3) | (type==GLM4)) | |
3314 { if (ker(&lf->sp) != WPARM) | |
3315 WARN(("nonparametric fit; correction is invalid")); | |
3316 cumulant(lf,des,sd); | |
3317 } | |
3318 haspc(&lf->pc) = tmp; | |
3319 lo = lf->fp.t0; | |
3320 hi = &lo[lf->fp.nvm]; | |
3321 switch(type) | |
3322 { | |
3323 case GLM1: | |
3324 return(st); | |
3325 case GLM2: /* centered scr */ | |
3326 lo[v] = kap[1]; | |
3327 hi[v] = sqrt(kap[2]); | |
3328 return(st); | |
3329 case GLM3: /* corrected 2 */ | |
3330 lo[v] = solve_secant(q2,scb_crit,0.0,2*scb_crit,0.000001,BDF_NONE,&err); | |
3331 return(st); | |
3332 case GLM4: /* corrected 2' */ | |
3333 u = fabs(p2(scb_crit)); | |
3334 max_p2 = MAX(max_p2,u); | |
3335 return(st); | |
3336 case GLDN: | |
3337 get_gldn(&lf->fp,des,lo,hi,v); | |
3338 return(st); | |
3339 } | |
3340 LERR(("procvscb2: invalid type")); | |
3341 return(st); | |
3342 } | |
3343 | |
3344 void scb(lf,des,res) | |
3345 lfit *lf; | |
3346 design *des; | |
3347 double *res; | |
3348 { double k1, k2, *lo, *hi, sig, thhat, nlx, rss[10]; | |
3349 int i, nterms; | |
3350 | |
3351 scb_des= des; | |
3352 | |
3353 npar(&lf->sp) = calcp(&lf->sp,lf->lfd.d); | |
3354 des_init(des,lf->lfd.n,npar(&lf->sp)); | |
3355 | |
3356 type = geth(&lf->fp); | |
3357 | |
3358 if (type >= 80) /* simultaneous */ | |
3359 { | |
3360 nterms = constants(lf,des,res); | |
3361 scb_crit = critval(0.05,res,nterms,lf->lfd.d,TWO_SIDED,0.0,GAUSS); | |
3362 type -= 10; | |
3363 } | |
3364 else /* pointwise */ | |
3365 { res[0] = 1; | |
3366 scb_crit = critval(0.05,res,1,lf->lfd.d,TWO_SIDED,0.0,GAUSS); | |
3367 } | |
3368 | |
3369 max_p2 = 0.0; | |
3370 lf->mdl.procv = procvscb2; | |
3371 nstartlf(des,lf); | |
3372 | |
3373 if ((fam(&lf->sp)&64)==64) | |
3374 { i = haspc(&lf->pc); haspc(&lf->pc) = 0; | |
3375 ressumm(lf,des,rss); | |
3376 haspc(&lf->pc) = i; | |
3377 sig = sqrt(rss[3]); | |
3378 } | |
3379 else sig = 1.0; | |
3380 | |
3381 lo = lf->fp.t0; | |
3382 hi = &lo[lf->fp.nvm]; | |
3383 for (i=0; i<lf->fp.nv; i++) | |
3384 { thhat = lf->fp.coef[i]; | |
3385 nlx = lf->fp.nlx[i]; | |
3386 switch(type) | |
3387 { | |
3388 case GLM1: /* basic scb */ | |
3389 lo[i] = thhat - scb_crit * sig * nlx; | |
3390 hi[i] = thhat + scb_crit * sig * nlx; | |
3391 break; | |
3392 case GLM2: | |
3393 k1 = lo[i]; | |
3394 k2 = hi[i]; | |
3395 lo[i] = thhat - k1*nlx - scb_crit*nlx*k2; | |
3396 hi[i] = thhat - k1*nlx + scb_crit*nlx*k2; | |
3397 break; | |
3398 case GLM3: | |
3399 k1 = lo[i]; | |
3400 lo[i] = thhat - k1*nlx; | |
3401 hi[i] = thhat + k1*nlx; | |
3402 case GLM4: /* corrected 2' */ | |
3403 lo[i] = thhat - (scb_crit-max_p2)*lf->fp.nlx[i]; | |
3404 hi[i] = thhat + (scb_crit-max_p2)*lf->fp.nlx[i]; | |
3405 break; | |
3406 case GLDN: | |
3407 break; | |
3408 } | |
3409 } | |
3410 } | |
3411 | |
3412 void initscb(lf) | |
3413 lfit *lf; | |
3414 { initstd(lf); | |
3415 PROCV(lf) = NULL; | |
3416 KEEPC(lf) = NVAR(lf)+1+k0_reqd(NVAR(lf),NOBS(lf),0); | |
3417 PPROC(lf) = scb; | |
3418 } | |
3419 /* | |
3420 * Copyright 1996-2006 Catherine Loader. | |
3421 */ | |
3422 #include "lfev.h" | |
3423 | |
3424 int procvsimple(des,lf,v) | |
3425 design *des; | |
3426 lfit *lf; | |
3427 int v; | |
3428 { int lf_status; | |
3429 lf_status = procv_nov(des,lf,v); | |
3430 VVAL(lf,v,0) = des->cf[cfn(des,0)]; | |
3431 return(lf_status); | |
3432 } | |
3433 | |
3434 void allocsimple(lf) | |
3435 lfit *lf; | |
3436 { lf->fp.coef = VVEC(lf,0); | |
3437 lf->fp.h = NULL; | |
3438 } | |
3439 | |
3440 void initsimple(lf) | |
3441 lfit *lf; | |
3442 { | |
3443 PROCV(lf) = procvsimple; | |
3444 ALLOC(lf) = allocsimple; | |
3445 PPROC(lf) = NULL; | |
3446 KEEPV(lf) = 1; | |
3447 KEEPC(lf) = 1; | |
3448 NOPC(lf) = 1; | |
3449 } | |
3450 /* | |
3451 * Copyright 1996-2006 Catherine Loader. | |
3452 */ | |
3453 #include "lfev.h" | |
3454 | |
3455 /* 3d+8 variables to keep: | |
3456 * d+1 coef+derivs. | |
3457 * d+1 sd's + derivs. | |
3458 * d+1 infl + derivs. | |
3459 * 3 likelihood and d.f's. | |
3460 * 1 bandwidth h | |
3461 * 1 degree. | |
3462 */ | |
3463 | |
3464 void allocstd(lf) | |
3465 lfit *lf; | |
3466 { int d; | |
3467 d = NVAR(lf); | |
3468 lf->fp.coef = VVEC(lf,0); | |
3469 lf->fp.nlx = VVEC(lf,d+1); | |
3470 lf->fp.t0 = VVEC(lf,2*d+2); | |
3471 lf->fp.lik = VVEC(lf,3*d+3); | |
3472 lf->fp.h = VVEC(lf,3*d+6); | |
3473 lf->fp.deg = VVEC(lf,3*d+7); | |
3474 } | |
3475 | |
3476 int procvstd(des,lf,v) | |
3477 design *des; | |
3478 lfit *lf; | |
3479 int v; | |
3480 { int d, p, nvm, i, k; | |
3481 double t0[1+MXDIM], vari[1+MXDIM]; | |
3482 k = procv_var(des,lf,v); | |
3483 if (lf_error) return(k); | |
3484 | |
3485 d = lf->lfd.d; | |
3486 p = npar(&lf->sp); | |
3487 nvm = lf->fp.nvm; | |
3488 | |
3489 if (k != LF_OK) lf_status_msg(k); | |
3490 | |
3491 lf->fp.lik[v] = des->llk; | |
3492 lf->fp.lik[nvm+v] = des->tr2; | |
3493 lf->fp.lik[2*nvm+v] = des->tr0 - des->tr2; | |
3494 | |
3495 for (i=0; i<des->ncoef; i++) | |
3496 vari[i] = des->V[p*cfn(des,0) + cfn(des,i)]; | |
3497 vari[0] = sqrt(vari[0]); | |
3498 if (vari[0]>0) for (i=1; i<des->ncoef; i++) vari[i] /= vari[0]; | |
3499 | |
3500 t0[0] = sqrt(des->f1[0]); | |
3501 if (t0[0]>0) for (i=1; i<des->ncoef; i++) t0[i] = des->f1[i]/t0[0]; | |
3502 | |
3503 if (dc(&lf->fp)) dercor(&lf->lfd,&lf->sp,des,des->cf); | |
3504 subparcomp(des,lf,des->cf); | |
3505 for (i=0; i<des->ncoef; i++) | |
3506 lf->fp.coef[i*lf->fp.nvm+v] = des->cf[cfn(des,i)]; | |
3507 | |
3508 subparcomp2(des,lf,vari,t0); | |
3509 for (i=0; i<des->ncoef; i++) | |
3510 { lf->fp.nlx[i*nvm+v] = vari[i]; | |
3511 lf->fp.t0[i*nvm+v] = t0[i]; | |
3512 } | |
3513 | |
3514 lf->fp.deg[v] = deg(&lf->sp); | |
3515 return(k); | |
3516 } | |
3517 | |
3518 void pprocstd(lf,des,res) | |
3519 lfit *lf; | |
3520 design *des; | |
3521 double *res; | |
3522 { | |
3523 ressumm(lf,des,res); | |
3524 } | |
3525 | |
3526 void initstd(lf) | |
3527 lfit *lf; | |
3528 { PROCV(lf) = procvstd; | |
3529 ALLOC(lf) = allocstd; | |
3530 PPROC(lf) = pprocstd; | |
3531 KEEPV(lf) = 3*NVAR(lf) + 8; | |
3532 KEEPC(lf) = 6; | |
3533 NOPC(lf) = 0; | |
3534 } | |
3535 /* | |
3536 * Copyright 1996-2006 Catherine Loader. | |
3537 */ | |
3538 #include "lfev.h" | |
3539 | |
3540 extern void procstd(), allocstd(); | |
3541 extern double robscale; | |
3542 | |
3543 double vocri(lk,t0,t2,pen) | |
3544 double lk, t0, t2, pen; | |
3545 { if (pen==0) return(-2*t0*lk/((t0-t2)*(t0-t2))); | |
3546 return((-2*lk+pen*t2)/t0); | |
3547 } | |
3548 | |
3549 double intvo(des,lf,c0,c1,a,p,t0,t20,t21) | |
3550 design *des; | |
3551 lfit *lf; | |
3552 double *c0, *c1, a, t0, t20, t21; | |
3553 int p; | |
3554 { double th, lk, link[LLEN]; | |
3555 int i, ii; | |
3556 lk = 0; | |
3557 for (i=0; i<des->n; i++) | |
3558 { ii = des->ind[i]; | |
3559 th = (1-a)*innerprod(c0,d_xi(des,i),p) + a*innerprod(c1,d_xi(des,i),p); | |
3560 stdlinks(link,&lf->lfd,&lf->sp,ii,th,robscale); | |
3561 lk += wght(des,ii)*link[ZLIK]; | |
3562 } | |
3563 des->llk = lk; | |
3564 return(vocri(des->llk,t0,(1-a)*t20+a*t21,pen(&lf->sp))); | |
3565 } | |
3566 | |
3567 int procvvord(des,lf,v) | |
3568 design *des; | |
3569 lfit *lf; | |
3570 int v; | |
3571 { double tr[6], gcv, g0, ap, coef[4][10], t2[4], th, md; | |
3572 int i, j, k, d1, i0, p1, ip; | |
3573 des->xev = evpt(&lf->fp,v); | |
3574 | |
3575 ap = pen(&lf->sp); | |
3576 if ((ap==0) & ((fam(&lf->sp)&63)!=TGAUS)) ap = 2.0; | |
3577 d1 = deg(&lf->sp); p1 = npar(&lf->sp); | |
3578 for (i=0; i<p1; i++) coef[0][i] = coef[1][i] = coef[2][i] = coef[3][i] = 0.0; | |
3579 i0 = 0; g0 = 0; | |
3580 ip = 1; | |
3581 | |
3582 for (i=deg0(&lf->sp); i<=d1; i++) | |
3583 { deg(&lf->sp) = i; | |
3584 des->p = npar(&lf->sp) = calcp(&lf->sp,lf->lfd.d); | |
3585 k = locfit(&lf->lfd,des,&lf->sp,0, i==deg0(&lf->sp),0); | |
3586 | |
3587 local_df(&lf->lfd,&lf->sp,des,tr); | |
3588 gcv = vocri(des->llk,tr[0],tr[2],ap); | |
3589 if ((i==deg0(&lf->sp)) || (gcv<g0)) { i0 = i; g0 = gcv; md = i; } | |
3590 | |
3591 for (j=0; j<des->p; j++) coef[i][j] = des->cf[j]; | |
3592 t2[i] = tr[2]; | |
3593 | |
3594 #ifdef RESEARCH | |
3595 if ((ip) && (i>deg0(&lf->sp))) | |
3596 { for (j=1; j<10; j++) | |
3597 { gcv = intvo(des,lf,coef[i-1],coef[i],j/10.0,des->p,tr[0],t2[i-1],t2[i]); | |
3598 if (gcv<g0) { g0 = gcv; md = i-1+j/10.0; } | |
3599 } | |
3600 } | |
3601 #endif | |
3602 } | |
3603 lf->fp.h[v] = des->h; | |
3604 if (lf->fp.h[v]<=0) WARN(("zero bandwidth in procvvord")); | |
3605 | |
3606 if (i0<d1) /* recompute the best fit */ | |
3607 { deg(&lf->sp) = i0; | |
3608 des->p = npar(&lf->sp) = calcp(&lf->sp,lf->lfd.d); | |
3609 k = locfit(&lf->lfd,des,&lf->sp,0,0,0); | |
3610 for (i=npar(&lf->sp); i<p1; i++) des->cf[i] = 0.0; | |
3611 i0 = md; if (i0==d1) i0--; | |
3612 th = md-i0; | |
3613 for (i=0; i<p1; i++) des->cf[i] = (1-th)*coef[i0][i]+th*coef[i0+1][i]; | |
3614 deg(&lf->sp) = d1; npar(&lf->sp) = p1; | |
3615 } | |
3616 | |
3617 for (i=0; i<p1; i++) lf->fp.coef[i*lf->fp.nvm+v] = des->cf[i]; | |
3618 lf->fp.deg[v] = md; | |
3619 return(k); | |
3620 } | |
3621 | |
3622 void initvord(lf) | |
3623 lfit *lf; | |
3624 { initstd(lf); | |
3625 PROCV(lf) = procvvord; | |
3626 ALLOC(lf) = allocstd; | |
3627 PPROC(lf) = NULL; | |
3628 KEEPC(lf) = 0; | |
3629 NOPC(lf) = 1; | |
3630 } | |
3631 /* | |
3632 * Copyright 1996-2006 Catherine Loader. | |
3633 */ | |
3634 /* | |
3635 * functions for computing and subtracting, adding the | |
3636 * parametric component | |
3637 */ | |
3638 | |
3639 #include "lfev.h" | |
3640 | |
3641 int noparcomp(sp) | |
3642 smpar *sp; | |
3643 { int tg; | |
3644 if (ubas(sp)) return(1); | |
3645 tg = fam(sp) & 63; | |
3646 if (tg<=THAZ) return(1); | |
3647 if (tg==TROBT) return(1); | |
3648 if (tg==TCAUC) return(1); | |
3649 if (tg==TQUANT) return(1); | |
3650 return(0); | |
3651 } | |
3652 | |
3653 int pc_reqd(d,p) | |
3654 int d, p; | |
3655 { return(d + 2*p + jac_reqd(p)); | |
3656 } | |
3657 | |
3658 void pcchk(pc,d,p,lc) | |
3659 paramcomp *pc; | |
3660 int d, p, lc; | |
3661 { int rw; | |
3662 double *z; | |
3663 | |
3664 rw = pc_reqd(d,p); | |
3665 if (pc->lwk < rw) | |
3666 { pc->wk = (double *)calloc(rw,sizeof(double)); | |
3667 if ( pc->wk == NULL ) { | |
3668 printf("Problem allocating memory for pc->wk\n");fflush(stdout); | |
3669 } | |
3670 pc->lwk= rw; | |
3671 } | |
3672 z = pc->wk; | |
3673 | |
3674 pc->xbar = z; z += d; | |
3675 pc->coef = z; z += p; | |
3676 pc->f = z; z += p; | |
3677 | |
3678 z = jac_alloc(&pc->xtwx,p,z); | |
3679 pc->xtwx.p = p; | |
3680 } | |
3681 | |
3682 void compparcomp(des,lfd,sp,pc,nopc) | |
3683 design *des; | |
3684 lfdata *lfd; | |
3685 smpar *sp; | |
3686 paramcomp *pc; | |
3687 int nopc; | |
3688 { int i, j, k, p; | |
3689 double wt, sw; | |
3690 | |
3691 if (lf_debug>1) mut_printf(" compparcomp:\n"); | |
3692 p = des->p; | |
3693 pcchk(pc,lfd->d,p,1); | |
3694 | |
3695 for (i=0; i<lfd->d; i++) pc->xbar[i] = 0.0; | |
3696 sw = 0.0; | |
3697 for (i=0; i<lfd->n; i++) | |
3698 { | |
3699 wt = prwt(lfd,i); | |
3700 sw += wt; | |
3701 for (j=0; j<lfd->d; j++) | |
3702 pc->xbar[j] += datum(lfd,j,i)*wt; | |
3703 des->ind[i] = i; | |
3704 wght(des,i) = 1.0; | |
3705 } | |
3706 for (i=0; i<lfd->d; i++) pc->xbar[i] /= sw; | |
3707 if ((nopc) || noparcomp(sp)) | |
3708 { haspc(pc) = 0; | |
3709 return; | |
3710 } | |
3711 haspc(pc) = 1; | |
3712 des->xev = pc->xbar; | |
3713 k = locfit(lfd,des,sp,0,0,0); | |
3714 if (k != LF_OK) lf_status_msg(k); | |
3715 if (lf_error) return; | |
3716 switch(k) | |
3717 { case LF_NOPT: return; | |
3718 case LF_INFA: return; | |
3719 case LF_NCON: return; | |
3720 case LF_OOB: return; | |
3721 case LF_NSLN: return; | |
3722 case LF_PF: | |
3723 WARN(("compparcomp: perfect fit")); | |
3724 case LF_OK: | |
3725 case LF_DONE: | |
3726 for (i=0; i<p; i++) | |
3727 { pc->coef[i] = des->cf[i]; | |
3728 pc->xtwx.dg[i] = des->xtwx.dg[i]; | |
3729 pc->xtwx.wk[i] = des->xtwx.wk[i]; | |
3730 } | |
3731 for (i=0; i<p*p; i++) | |
3732 { pc->xtwx.Z[i] = des->xtwx.Z[i]; | |
3733 pc->xtwx.Q[i] = des->xtwx.Q[i]; | |
3734 } | |
3735 pc->xtwx.sm = des->xtwx.sm; | |
3736 pc->xtwx.st = des->xtwx.st; | |
3737 return; | |
3738 default: | |
3739 LERR(("compparcomp: locfit unknown return status %d",k)); | |
3740 return; | |
3741 } | |
3742 } | |
3743 | |
3744 void subparcomp(des,lf,coef) | |
3745 design *des; | |
3746 lfit *lf; | |
3747 double *coef; | |
3748 { int i, nd; | |
3749 deriv *dv; | |
3750 paramcomp *pc; | |
3751 | |
3752 pc = &lf->pc; | |
3753 if (!haspc(pc)) return; | |
3754 | |
3755 dv = &lf->dv; nd = dv->nd; | |
3756 fitfun(&lf->lfd, &lf->sp, des->xev,pc->xbar,des->f1,dv); | |
3757 coef[0] -= innerprod(pc->coef,des->f1,pc->xtwx.p); | |
3758 if (des->ncoef == 1) return; | |
3759 | |
3760 dv->nd = nd+1; | |
3761 for (i=0; i<lf->lfd.d; i++) | |
3762 { dv->deriv[nd] = i; | |
3763 fitfun(&lf->lfd, &lf->sp, des->xev,pc->xbar,des->f1,dv); | |
3764 coef[i+1] -= innerprod(pc->coef,des->f1,pc->xtwx.p); | |
3765 } | |
3766 dv->nd = nd; | |
3767 } | |
3768 | |
3769 void subparcomp2(des,lf,vr,il) | |
3770 design *des; | |
3771 lfit *lf; | |
3772 double *vr, *il; | |
3773 { double t0, t1; | |
3774 int i, nd; | |
3775 deriv *dv; | |
3776 paramcomp *pc; | |
3777 | |
3778 pc = &lf->pc; | |
3779 if (!haspc(pc)) return; | |
3780 | |
3781 dv = &lf->dv; nd = dv->nd; | |
3782 | |
3783 fitfun(&lf->lfd, &lf->sp, des->xev,pc->xbar,des->f1,dv); | |
3784 for (i=0; i<npar(&lf->sp); i++) pc->f[i] = des->f1[i]; | |
3785 jacob_solve(&pc->xtwx,des->f1); | |
3786 t0 = sqrt(innerprod(pc->f,des->f1,pc->xtwx.p)); | |
3787 vr[0] -= t0; | |
3788 il[0] -= t0; | |
3789 if ((t0==0) | (des->ncoef==1)) return; | |
3790 | |
3791 dv->nd = nd+1; | |
3792 for (i=0; i<lf->lfd.d; i++) | |
3793 { dv->deriv[nd] = i; | |
3794 fitfun(&lf->lfd, &lf->sp, des->xev,pc->xbar,pc->f,dv); | |
3795 t1 = innerprod(pc->f,des->f1,pc->xtwx.p)/t0; | |
3796 vr[i+1] -= t1; | |
3797 il[i+1] -= t1; | |
3798 } | |
3799 dv->nd = nd; | |
3800 } | |
3801 | |
3802 double addparcomp(lf,x,c) | |
3803 lfit *lf; | |
3804 double *x; | |
3805 int c; | |
3806 { double y; | |
3807 paramcomp *pc; | |
3808 | |
3809 pc = &lf->pc; | |
3810 if (!haspc(pc)) return(0.0); | |
3811 fitfun(&lf->lfd, &lf->sp, x,pc->xbar,pc->f,&lf->dv); | |
3812 if (c==PCOEF) return(innerprod(pc->coef,pc->f,pc->xtwx.p)); | |
3813 if ((c==PNLX)|(c==PT0)|(c==PVARI)) | |
3814 { y = sqrt(jacob_qf(&pc->xtwx,pc->f)); | |
3815 return(y); | |
3816 } | |
3817 return(0.0); | |
3818 } | |
3819 /* | |
3820 * Copyright 1996-2006 Catherine Loader. | |
3821 */ | |
3822 #include "lfev.h" | |
3823 | |
3824 /* | |
3825 preplot(): interpolates the fit to a new set of points. | |
3826 lf -- the fit structure. | |
3827 x -- the points to predict at. | |
3828 f -- vector to return the predictions. | |
3829 se -- vector to return std errors (NULL if not req'd) | |
3830 band-- char for conf band type. ('n'=none, 'g'=global etc.) | |
3831 n -- no of predictions (or vector of margin lengths for grid) | |
3832 where -- where to predict: | |
3833 1 = points in the array x. | |
3834 2 = grid defined by margins in x. | |
3835 3 = data points from lf (ignore x). | |
3836 4 = fit points from lf (ignore x). | |
3837 what -- what to predict. | |
3838 (PCOEF etc; see lfcons.h file) | |
3839 | |
3840 */ | |
3841 | |
3842 #define NWH 8 | |
3843 static char *whtyp[NWH] = { "coef", "nlx", "infl", "band", | |
3844 "degr", "like", "rdf", "vari" }; | |
3845 static int whval[NWH] = { PCOEF, PNLX, PT0, PBAND, PDEGR, PLIK, PRDF, PVARI }; | |
3846 int ppwhat(z) | |
3847 char *z; | |
3848 { int val; | |
3849 | |
3850 val = pmatch(z, whtyp, whval, NWH, -1); | |
3851 if (val==-1) LERR(("Unknown what = %s",z)); | |
3852 return(val); | |
3853 } | |
3854 | |
3855 static char cb; | |
3856 double *sef, *fit, sigmahat; | |
3857 | |
3858 void predptall(lf,x,what,ev,i) | |
3859 lfit *lf; | |
3860 double *x; | |
3861 int what, ev, i; | |
3862 { double lik, rdf; | |
3863 fit[i] = dointpoint(lf,x,what,ev,i); | |
3864 if (cb=='n') return; | |
3865 sef[i] = dointpoint(lf,x,PNLX,ev,i); | |
3866 if (cb=='g') | |
3867 { sef[i] *= sigmahat; | |
3868 return; | |
3869 } | |
3870 if (cb=='l') | |
3871 { lik = dointpoint(lf,x,PLIK,ev,i); | |
3872 rdf = dointpoint(lf,x,PRDF,ev,i); | |
3873 sef[i] *= sqrt(-2*lik/rdf); | |
3874 return; | |
3875 } | |
3876 if (cb=='p') | |
3877 { sef[i] = sigmahat*sqrt(1+sef[i]*sef[i]); | |
3878 return; | |
3879 } | |
3880 } | |
3881 | |
3882 void predptdir(lf,des,x,what,i) | |
3883 lfit *lf; | |
3884 design *des; | |
3885 double *x; | |
3886 int what, i; | |
3887 { int needcv; | |
3888 des->xev = x; | |
3889 needcv = (what==PVARI) | (what==PNLX) | (what==PT0) | (what==PRDF); | |
3890 locfit(&lf->lfd,des,&lf->sp,0,1,needcv); | |
3891 switch(what) | |
3892 { case PCOEF: fit[i] = des->cf[0]; break; | |
3893 case PVARI: fit[i] = des->V[0]; break; | |
3894 case PNLX: fit[i] = sqrt(des->V[0]); break; | |
3895 case PT0: fit[i] = des->f1[0]; break; | |
3896 case PBAND: fit[i] = des->h; break; | |
3897 case PDEGR: fit[i] = deg(&lf->sp); break; | |
3898 case PLIK: fit[i] = des->llk; break; | |
3899 case PRDF: fit[i] = des->tr0 - des->tr2; break; | |
3900 default: LERR(("unknown what in predptdir")); | |
3901 } | |
3902 } | |
3903 | |
3904 void prepvector(lf,des,x,n,what,dir) /* interpolate a vector */ | |
3905 lfit *lf; | |
3906 design *des; | |
3907 double **x; | |
3908 int n, what, dir; | |
3909 { int i, j; | |
3910 double xx[MXDIM]; | |
3911 for (i=0; i<n; i++) | |
3912 { for (j=0; j<lf->fp.d; j++) xx[j] = x[j][i]; | |
3913 if (dir) | |
3914 predptdir(lf,des,xx,what,i); | |
3915 else | |
3916 predptall(lf,xx,what,ev(&lf->evs),i); | |
3917 if (lf_error) return; | |
3918 } | |
3919 } | |
3920 | |
3921 void prepfitp(lf,what) | |
3922 lfit *lf; | |
3923 int what; | |
3924 { int i; | |
3925 for (i=0; i<lf->fp.nv; i++) | |
3926 { predptall(lf,evpt(&lf->fp,i),what,EFITP,i); | |
3927 if (lf_error) return; | |
3928 } | |
3929 } | |
3930 | |
3931 void prepgrid(lf,des,x,mg,n,what,dir) /* interpolate a grid given margins */ | |
3932 lfit *lf; | |
3933 design *des; | |
3934 double **x; | |
3935 int *mg, dir, n, what; | |
3936 { int i, ii, j, d; | |
3937 double xv[MXDIM]; | |
3938 d = lf->fp.d; | |
3939 for (i=0; i<n; i++) | |
3940 { ii = i; | |
3941 for (j=0; j<d; j++) | |
3942 { xv[j] = x[j][ii%mg[j]]; | |
3943 ii /= mg[j]; | |
3944 } | |
3945 if (dir) | |
3946 predptdir(lf,des,xv,what,i); | |
3947 else | |
3948 predptall(lf,xv,what,ev(&lf->evs),i); | |
3949 if (lf_error) return; | |
3950 } | |
3951 } | |
3952 | |
3953 void preplot(lf,x,f,se,band,mg,where,what,dir) | |
3954 lfit *lf; | |
3955 double **x, *f, *se; | |
3956 int *mg, where, what, dir; | |
3957 char band; | |
3958 { int d, i, n; | |
3959 double *xx[MXDIM]; | |
3960 design ppdes; | |
3961 d = lf->fp.d; | |
3962 fit = f; | |
3963 sef = se; | |
3964 cb = band; | |
3965 if (cb!='n') sigmahat = sqrt(rv(&lf->fp)); | |
3966 if (dir) des_init(&ppdes,lf->lfd.n,npar(&lf->sp)); | |
3967 | |
3968 switch(where) | |
3969 { case 1: /* vector */ | |
3970 n = mg[0]; | |
3971 prepvector(lf,&ppdes,x,n,what,dir); | |
3972 break; | |
3973 case 2: /* grid */ | |
3974 n = 1; | |
3975 for (i=0; i<d; i++) n *= mg[i]; | |
3976 prepgrid(lf,&ppdes,x,mg,n,what,dir); | |
3977 break; | |
3978 case 3: /* data */ | |
3979 n = lf->lfd.n; | |
3980 if ((ev(&lf->evs)==EDATA) | (ev(&lf->evs)==ECROS)) | |
3981 { prepfitp(lf,what); | |
3982 dir = 0; | |
3983 } | |
3984 else | |
3985 { for (i=0; i<d; i++) xx[i] = dvari(&lf->lfd,i); | |
3986 prepvector(lf,&ppdes,xx,n,what,dir); | |
3987 } | |
3988 break; | |
3989 case 4: /* fit points */ | |
3990 n = lf->fp.nv; dir = 0; | |
3991 prepfitp(lf,what); | |
3992 break; | |
3993 default: | |
3994 LERR(("unknown where in preplot")); | |
3995 } | |
3996 | |
3997 if ((!dir) && ((what==PT0)|(what==PVARI))) | |
3998 for (i=0; i<n; i++) f[i] = f[i]*f[i]; | |
3999 } | |
4000 /* | |
4001 * Copyright 1996-2006 Catherine Loader. | |
4002 */ | |
4003 #include "lfev.h" | |
4004 | |
4005 int procv_nov(des,lf,v) | |
4006 design *des; | |
4007 lfit *lf; | |
4008 int v; | |
4009 { int lf_status; | |
4010 | |
4011 if (lf_debug>1) mut_printf(" procveraw: %d\n",v); | |
4012 des->xev = evpt(&lf->fp,v); | |
4013 | |
4014 if (acri(&lf->sp)==ANONE) | |
4015 lf_status = locfit(&lf->lfd,des,&lf->sp,0,1,0); | |
4016 else | |
4017 lf_status = alocfit(&lf->lfd,&lf->sp,&lf->dv,des,0); | |
4018 if (lf->fp.h != NULL) lf->fp.h[v] = des->h; | |
4019 | |
4020 return(lf_status); | |
4021 } | |
4022 | |
4023 int procv_var(des,lf,v) | |
4024 design *des; | |
4025 lfit *lf; | |
4026 int v; | |
4027 { int i, lf_status; | |
4028 | |
4029 if (lf_debug>1) mut_printf(" procvraw: %d\n",v); | |
4030 des->xev = evpt(&lf->fp,v); | |
4031 | |
4032 if (acri(&lf->sp)==ANONE) | |
4033 lf_status = locfit(&lf->lfd,des,&lf->sp,0,1,1); | |
4034 else | |
4035 lf_status = alocfit(&lf->lfd,&lf->sp,&lf->dv,des,1); | |
4036 if (lf->fp.h != NULL) lf->fp.h[v] = des->h; | |
4037 | |
4038 return(lf_status); | |
4039 } | |
4040 /* | |
4041 * Copyright 1996-2006 Catherine Loader. | |
4042 */ | |
4043 /* | |
4044 * startmodule(lf,des,mod,dir) -- the standard entry point. | |
4045 * des and lf are pointers to the design and fit structures. | |
4046 * mod - module name. Set to NULL if the module is already | |
4047 * initialized. | |
4048 * dir - for dynamic modules, the directory. | |
4049 * | |
4050 * initmodule(mdl,mod,dir,lf) | |
4051 * direct call for module initialization. | |
4052 * | |
4053 */ | |
4054 | |
4055 #include "lfev.h" | |
4056 | |
4057 #ifdef WINDOWS | |
4058 | |
4059 #define DIRSEP '\\' | |
4060 #define PATHSEP ';' | |
4061 | |
4062 #else | |
4063 | |
4064 #define DIRSEP '/' | |
4065 #define PATHSEP ':' | |
4066 | |
4067 #endif | |
4068 | |
4069 | |
4070 #ifdef ALLOW_MODULES | |
4071 | |
4072 #ifdef WINDOWS | |
4073 #include <windows.h> | |
4074 #define DLEXT "dll" | |
4075 #define DLOPEN(x) LoadLibrary(x) | |
4076 #define DLSYM GetProcAddress | |
4077 | |
4078 #else | |
4079 | |
4080 #include <dlfcn.h> | |
4081 #define DLEXT "so" | |
4082 #define DLOPEN(x) dlopen(x,RTLD_LAZY) | |
4083 #define DLSYM dlsym | |
4084 #endif | |
4085 | |
4086 #endif | |
4087 | |
4088 static double fpkap[6]; | |
4089 void fitpt_init(fp) | |
4090 fitpt *fp; | |
4091 { | |
4092 dc(fp) = 0; | |
4093 geth(fp) = GSTD; | |
4094 fp->nv = fp->nvm = 0; | |
4095 if (fp->kap==NULL) fp->kap = fpkap; | |
4096 } | |
4097 | |
4098 void lfit_init(lf) | |
4099 lfit *lf; | |
4100 { | |
4101 lfdata_init(&lf->lfd); | |
4102 evstruc_init(&lf->evs); | |
4103 smpar_init(&lf->sp,&lf->lfd); | |
4104 deriv_init(&lf->dv); | |
4105 fitpt_init(&lf->fp); | |
4106 lf->mdl.np = 0; | |
4107 } | |
4108 | |
4109 void fitdefault(lf) | |
4110 lfit *lf; | |
4111 { WARN(("fitdefault deprecated -- use lfit_init()")); | |
4112 lfit_init(lf); | |
4113 } | |
4114 | |
4115 void set_flim(lfd,evs) | |
4116 lfdata *lfd; | |
4117 evstruc *evs; | |
4118 { int i, j, d, n; | |
4119 double z, mx, mn, *bx; | |
4120 | |
4121 if (ev(evs)==ESPHR) return; | |
4122 d = lfd->d; n = lfd->n; | |
4123 bx = evs->fl; | |
4124 for (i=0; i<d; i++) | |
4125 if (bx[i]==bx[i+d]) | |
4126 { if (lfd->sty[i]==STANGL) | |
4127 { bx[i] = 0.0; bx[i+d] = 2*PI*lfd->sca[i]; | |
4128 } | |
4129 else | |
4130 { mx = mn = datum(lfd,i,0); | |
4131 for (j=1; j<n; j++) | |
4132 { mx = MAX(mx,datum(lfd,i,j)); | |
4133 mn = MIN(mn,datum(lfd,i,j)); | |
4134 } | |
4135 if (lfd->xl[i]<lfd->xl[i+d]) /* user set xlim; maybe use them. */ | |
4136 { z = mx-mn; | |
4137 if (mn-0.2*z < lfd->xl[i]) mn = lfd->xl[i]; | |
4138 if (mx+0.2*z > lfd->xl[i+d]) mx = lfd->xl[i+d]; | |
4139 } | |
4140 bx[i] = mn; | |
4141 bx[i+d] = mx; | |
4142 } | |
4143 } | |
4144 } | |
4145 | |
4146 double vvari(v,n) | |
4147 double *v; | |
4148 int n; | |
4149 { int i; | |
4150 double xb, s2; | |
4151 xb = s2 = 0.0; | |
4152 for (i=0; i<n; i++) xb += v[i]; | |
4153 xb /= n; | |
4154 for (i=0; i<n; i++) s2 += SQR(v[i]-xb); | |
4155 return(s2/(n-1)); | |
4156 } | |
4157 | |
4158 void set_scales(lfd) | |
4159 lfdata *lfd; | |
4160 { int i; | |
4161 for (i=0; i<lfd->d; i++) | |
4162 if (lfd->sca[i]<=0) /* set automatic scales */ | |
4163 { if (lfd->sty[i]==STANGL) | |
4164 lfd->sca[i] = 1.0; | |
4165 else lfd->sca[i] = sqrt(vvari(lfd->x[i],lfd->n)); | |
4166 } | |
4167 } | |
4168 | |
4169 void nstartlf(des,lf) | |
4170 design *des; | |
4171 lfit *lf; | |
4172 { int i, d, n; | |
4173 | |
4174 if (lf_debug>0) mut_printf("nstartlf\n"); | |
4175 n = lf->lfd.n; | |
4176 d = lf->lfd.d; | |
4177 npar(&lf->sp) = calcp(&lf->sp,d); | |
4178 | |
4179 des_init(des,n,npar(&lf->sp)); | |
4180 set_scales(&lf->lfd); | |
4181 set_flim(&lf->lfd,&lf->evs); | |
4182 compparcomp(des,&lf->lfd,&lf->sp,&lf->pc,lf->mdl.nopc); | |
4183 if (lf_error) return; | |
4184 makecfn(&lf->sp,des,&lf->dv,lf->lfd.d); | |
4185 | |
4186 lf->lfd.ord = 0; | |
4187 if ((d==1) && (lf->lfd.sty[0]!=STANGL)) | |
4188 { i = 1; | |
4189 while ((i<n) && (datum(&lf->lfd,0,i)>=datum(&lf->lfd,0,i-1))) i++; | |
4190 lf->lfd.ord = (i==n); | |
4191 } | |
4192 for (i=0; i<npar(&lf->sp); i++) des->fix[i] = 0; | |
4193 | |
4194 lf->fp.d = lf->lfd.d; | |
4195 lf->fp.hasd = (des->ncoef==(1+lf->fp.d)); | |
4196 lf->fp.nv = lf->evs.nce = 0; | |
4197 | |
4198 if (lf_debug>1) mut_printf("call eval structure %d\n",ev(&lf->evs)); | |
4199 switch(ev(&lf->evs)) | |
4200 { case EPHULL: triang_start(des,lf); break; | |
4201 case EDATA: dataf(des,lf); break; | |
4202 case ECROS: crossf(des,lf); break; | |
4203 case EGRID: gridf(des,lf); break; | |
4204 case ETREE: atree_start(des,lf); break; | |
4205 case EKDCE: kt(&lf->sp) = KCE; | |
4206 case EKDTR: kdtre_start(des,lf); break; | |
4207 case EPRES: preset(des,lf); break; | |
4208 case EXBAR: xbarf(des,lf); break; | |
4209 case ENONE: return; | |
4210 case ESPHR: sphere_start(des,lf); break; | |
4211 case ESPEC: lf->evs.espec(des,lf); break; | |
4212 default: LERR(("startlf: Invalid evaluation structure %d",ev(&lf->evs))); | |
4213 } | |
4214 | |
4215 /* renormalize for family=density */ | |
4216 if ((de_renorm) && (fam(&lf->sp)==TDEN)) dens_renorm(lf,des); | |
4217 } | |
4218 | |
4219 /* | |
4220 * getnextdir() gets the next dir from a string dirpath="dir1:dir2:dir3:..." | |
4221 * (;-separated on windows). | |
4222 * The directory is returned through dirnext, and the function returns | |
4223 * a pointer to the next string. | |
4224 * typical usage is recursive, dirpath = getnextdir(dirpath,dirnext). | |
4225 * with the above example, this sets dirnext="dir1" and dirpath="dir2:dir3:...". | |
4226 * if the input dirpath has no :, then it is copied to dirnext, and return is "". | |
4227 * if input dirpath is "", dirnext is set to "", and null pointer returned. | |
4228 */ | |
4229 char *getnextdir(dirpath,dirnext) | |
4230 char *dirpath, *dirnext; | |
4231 { char *z; | |
4232 if (strlen(dirpath)==0) | |
4233 { sprintf(dirnext,""); | |
4234 return(NULL); | |
4235 } | |
4236 | |
4237 z = strchr(dirpath,PATHSEP); | |
4238 if (z==NULL) | |
4239 { sprintf(dirnext,"%s%c",dirpath,DIRSEP); | |
4240 return(&dirpath[strlen(dirnext)]); | |
4241 } | |
4242 | |
4243 *z = '\0'; | |
4244 sprintf(dirnext,"%s%c",dirpath,DIRSEP); | |
4245 return(++z); | |
4246 } | |
4247 | |
4248 int initmodule(mdl, mod, dir, lf) | |
4249 module *mdl; | |
4250 lfit *lf; | |
4251 char *mod, *dir; | |
4252 { int n, d, p; | |
4253 #ifdef ALLOW_MODULES | |
4254 #ifdef WINDOWS | |
4255 HINSTANCE res; | |
4256 typedef void (CALLBACK* DLLFN)(); | |
4257 DLLFN init; | |
4258 #else | |
4259 void *res; | |
4260 void (*init)(); | |
4261 #endif | |
4262 char distname[500]; | |
4263 #endif | |
4264 | |
4265 n = lf->lfd.n; | |
4266 d = lf->lfd.d; | |
4267 p = npar(&lf->sp) = calcp(&lf->sp,d); | |
4268 | |
4269 mdl->isset = 1; | |
4270 PPROC(lf) = NULL; | |
4271 if (strcmp(mod,"std")==0) { initstd(lf); return(1); } | |
4272 if (strcmp(mod,"simple")==0) { initsimple(lf); return(1); } | |
4273 if (strcmp(mod,"allcf")==0) { initallcf(lf); return(1); } | |
4274 if (strcmp(mod,"hatm")==0) { inithatm(lf); return(1); } | |
4275 if (strcmp(mod,"kappa")==0) { initkappa(lf); return(1); } | |
4276 if (strcmp(mod,"lscv")==0) { initlscv(lf); return(1); } | |
4277 if (strcmp(mod,"gamf")==0) { initgam(lf); return(1); } | |
4278 if (strcmp(mod,"gamp")==0) { initgam(lf); return(1); } | |
4279 if (strcmp(mod,"rband")==0) { initrband(lf); return(1); } | |
4280 if (strcmp(mod,"scb")==0) { initscb(lf); return(1); } | |
4281 if (strcmp(mod,"vord")==0) { initvord(lf); return(1); } | |
4282 | |
4283 #ifdef ALLOW_MODULES | |
4284 while (dir != NULL) | |
4285 { | |
4286 dir = getnextdir(dir,distname); | |
4287 sprintf(&distname[strlen(distname)],"mod%s.%s",mod,DLEXT); | |
4288 res = DLOPEN(distname); | |
4289 if (res==NULL) | |
4290 { | |
4291 #ifdef WINDOWS | |
4292 mut_printf("LoadLibrary failed: %s, %d\n",distname,GetLastError()); | |
4293 #else | |
4294 mut_printf("dlopen failed: %s\n",dlerror()); | |
4295 #endif | |
4296 } | |
4297 else | |
4298 { | |
4299 #ifdef WINDOWS | |
4300 mut_printf("LoadLibrary success: %s\n",distname); | |
4301 #else | |
4302 mut_printf("dlopen success: %s\n",distname); | |
4303 #endif | |
4304 sprintf(distname,"init%s",mod); | |
4305 init = (void *)DLSYM(res,distname); | |
4306 if (init==NULL) | |
4307 { mut_printf("I can't find %s() function.\n",distname); | |
4308 mdl->isset = 0; | |
4309 return(0); | |
4310 } | |
4311 init(lf); | |
4312 return(1); | |
4313 } | |
4314 } | |
4315 #endif | |
4316 | |
4317 mdl->isset = 0; | |
4318 return(0); | |
4319 } | |
4320 | |
4321 /* | |
4322 * startmodule is the entry point to launch the fit. | |
4323 * if mod is provided, will first initialize the module. | |
4324 * if mod==NULL, assumes the module has been initialized separately. | |
4325 */ | |
4326 void startmodule(lf,des,mod,dir) | |
4327 lfit *lf; | |
4328 design *des; | |
4329 char *mod, *dir; | |
4330 { int z; | |
4331 | |
4332 if (mod != NULL) | |
4333 { z = initmodule(&lf->mdl,mod,dir,lf); | |
4334 if (!z) return; | |
4335 } | |
4336 | |
4337 lf->fp.nv = lf->evs.nce = 0; | |
4338 if (lf_error) return; | |
4339 if (PROCV(lf) != NULL) nstartlf(des,lf); | |
4340 if (lf_error) return; | |
4341 if (PPROC(lf) != NULL) PPROC(lf)(lf,des,lf->fp.kap); | |
4342 } | |
4343 | |
4344 /* for compatability, more or less. */ | |
4345 void startlf(des,lf,vfun,nopc) | |
4346 design *des; | |
4347 lfit *lf; | |
4348 int (*vfun)(), nopc; | |
4349 { int z; | |
4350 z = initmodule(&lf->mdl,"std",NULL,lf); | |
4351 if (!z) return; | |
4352 lf->mdl.procv = vfun; | |
4353 lf->mdl.nopc = nopc; | |
4354 nstartlf(des,lf); | |
4355 } |