84 int i, j, niter=0, nn, calcVar=1;
85 double c, m, f, xb=0.0, yb=0.0, qa=0.0, qb=0.0, qc, ss=0.0, s1, s2, wsum=0.0;
86 double xsum=0.0, x2sum=0.0, ysum=0.0, xysum=0.0, delta, discr, sqdis;
87 double m_1, m_2, bcont, m2=0.0, w2;
88 double u, v, AA, BB, CC, DD, EE, FF, GG, HH, JJ;
89 double varc, varm, dmx, dmy, dcx, dcy;
95 if(0) {fprintf(stdout,
"llsqwt()\n"); fflush(stdout);}
99 for(i=0; i<n; i++) printf(
"%e +- %e %e +- %e\n",
100 x[i], wx[i], y[i], wy[i]);
102 if(tol<1.0e-100)
return(1);
103 if(w==NULL)
return(1);
105 if(sic==NULL || sslope==NULL || cx==NULL || cy==NULL) calcVar=0;
111 if(f==0.0) {*slope=*ic=*sic=*sslope=*nwss=w[0]=w[1]=0.0;
return(0);}
112 *slope=(y[1]-y[0])/f; *ic=y[0]-(*slope)*x[0];
113 *sic=*sslope=0.; w[0]=1.0; w[1]=1.0; *nwss=0.0;
123 xsum+=x[i]; ysum+=y[i]; x2sum+=x[i]*x[i]; xysum+=x[i]*y[i];
125 delta=(double)n*x2sum - xsum*xsum;
128 if(0) printf(
"x axis values contain only zeroes.\n");
129 *slope=*ic=*sic=*sslope=*nwss=w[0]=w[1]=0.0;
132 m=((double)n*xysum - xsum*ysum)/delta;
133 c=(x2sum*ysum - xsum*xysum)/delta;
134 if(0) printf(
"initial guesses: a=%e b=%e\n", c, m);
138 while(fabs(m-bcont)>tol && niter<20) {
139 if(0) printf(
" %d. iteration, improvement=%g, tol=%g\n", niter, fabs(m-bcont), tol);
143 for(i=0, nn=0; i<n; i++) {
144 if(wx[i]<=0.0 || wy[i]<=0.0) w[i]=0.0;
145 else {w[i]=wx[i]*wy[i]/(m2*wy[i]+wx[i]); nn++;}
149 if(0) printf(
"less than two points with weight > 0.\n");
150 *slope=*ic=*sic=*sslope=*nwss=0.0;
154 for(i=0, xb=yb=wsum=0.0; i<n; i++) {xb+=w[i]*x[i]; yb+=w[i]*y[i]; wsum+=w[i];}
155 if(wsum<=0.0)
return(2);
157 if(0) printf(
"barycentre: xb=%g yb=%g\n", xb, yb);
160 for(i=0, qa=qb=qc=0.0; i<n; i++)
if(w[i]>0.0) {
161 u=x[i]-xb; v=y[i]-yb; w2=w[i]*w[i];
163 qb += w2*(u*u/wy[i] - v*v/wx[i]);
166 if(0) printf(
"quadratic coefs: qa=%g qb=%g qc=%g\n", qa, qb, qc);
170 for(i=0, ss=0.0; i<n; i++) {f=v=y[i]-yb; ss+=w[i]*f*f;}
174 for(i=0, ss=0.0; i<n; i++) {u=x[i]-xb; v=y[i]-yb; f=v-m*u; ss+=w[i]*f*f;}
177 discr=qb*qb-4.0*qa*qc;
if(discr<=0.0) sqdis=0.0;
else sqdis=sqrt(discr);
179 m_1=(-qb+sqdis)/(2.0*qa); m_2=(-qb-sqdis)/(2.0*qa);
181 for(i=0, s1=s2=0.0; i<n; i++) {
182 u=x[i]-xb; v=y[i]-yb;
183 f=v-m_1*u; s1+=w[i]*f*f;
184 f=v-m_2*u; s2+=w[i]*f*f;
187 if(s1<=s2) {m=m_1; ss=s1;}
else {m=m_2; ss=s2;}
191 if(0) printf(
"iterated parameters: c=%e m=%e\n", c, m);
194 *ic=c; *slope=m; *nwss=sqrt(ss)/wsum;
196 fprintf(stdout,
"c=%14.7e m=%14.7e ss=%14.7e niter=%d\n", c, m, ss, niter);
200 if(!calcVar)
return(0);
207 f=w[i]*(c + m*x[i] - y[i]);
208 cx[i]=x[i]-f*m/wx[i]; cy[i]=y[i]+f/wy[i];
210 cx[i]=x[i]; cy[i]=y[i];
220 for(i=nn=0; i<n; i++)
if(w[i]>0.0) nn++;
221 if(nn<3) {*sslope=*sic=0.0;
return(0);}
224 for(i=0, xb=yb=wsum=0.0; i<n; i++) {xb+=w[i]*cx[i]; yb+=w[i]*cy[i]; wsum+=w[i];}
225 if(wsum<=0.0)
return(2);
227 if(0) printf(
"barycentre: xb=%g yb=%g\n", xb, yb);
231 for(i=0; i<n; i++)
if(w[i]>0.0) {
232 u=cx[i]-xb; v=cy[i]-yb; w2=w[i]*w[i];
234 qb += w2*(u*u/wy[i] - v*v/wx[i]);
239 HH*=-2.0*m/wsum; JJ*=-2.0*m/wsum;
240 if(0) printf(
"quadratic coefs: qa=%g qb=%g qc=%g ; HH=%g JJ=%g\n", qa, qb, qc, HH, JJ);
242 for(i=0; i<n; i++)
if(w[i]>0.0) {
243 u=cx[i]-xb; v=cy[i]-yb; w2=w[i]*w[i];
244 AA += w[i]*w[i]*w[i]*u*v / (wx[i]*wx[i]);
245 BB -= w2 * (4.0*m*(w[i]/wx[i])*(u*u/wy[i]-v*v/wx[i]) - 2.0*v*HH/wx[i] + 2.0*u*JJ/wy[i]);
246 CC -= (w2/wy[i]) * (4.0*m*w[i]*u*v/wx[i] + v*JJ + u*HH);
248 if(m!=0) AA = 4.0*m*AA - wsum*HH*JJ/m;
else AA=0.0;
249 if(0) printf(
"AA=%g BB=%g CC=%g\n", AA, BB, CC);
252 for(j=0; j<n; j++)
if(w[j]>0.0) {
255 for(i=0; i<n; i++)
if(w[i]>0.0) {
256 u=cx[i]-xb; v=cy[i]-yb; w2=w[i]*w[i];
257 if(i==j) delta=1.0;
else delta=0.0;
258 f = delta - w[j]/wsum;
259 DD += (w2*v/wx[i])*f;
260 EE += (w2*u/wy[i])*f;
261 FF += (w2*v/wy[i])*f;
262 GG += (w2*u/wx[i])*f;
266 f = (2.0*m*qa + qb - AA*m2 + BB*m - CC); m2=m*m;
267 dmx = -(m2*DD + m*EE - FF) / f;
268 dmy = -(m2*GG - 2.0*m*DD - EE/2.0) / f;
269 dcx = (HH - m*JJ - xb)*dmx - m*w[j]/wsum;
270 dcy = (HH - m*JJ - xb)*dmy + w[j]/wsum;
272 varm += dmy*dmy/wy[j] + dmx*dmx/wx[j];
273 varc += dcy*dcy/wy[j] + dcx*dcx/wx[j];
275 printf(
"DD=%g EE=%g FF=%g GG=%g dmx=%g dmy=%g dcx=%g dcy=%g\n",
276 DD, EE, FF, GG, dmx, dmy, dcx, dcy);
278 varm *= ss/(double)(nn-2);
279 varc *= ss/(double)(nn-2);
280 if(0) printf(
"varm=%g varc=%g\n", varm, varc);
281 *sslope = sqrt(varm);
283 if(0) {fprintf(stdout,
"sslope=%14.7e sic=%14.7e\n", *sslope, *sic);}
326 int from, to, ret, from_min, to_min;
327 double *w, lic, lslope, lnwss=1.0E+100, nwss_min=1.0E+100;
330 if(x==NULL || y==NULL || nr<min_nr || nr<2)
return(1);
332 if(min_nr<4 || (mode!=0 && mode!=1))
return(2);
335 w=(
double*)malloc(nr*
sizeof(
double));
if(w==NULL)
return(3);
338 nwss_min=9.99E+99; from_min=to_min=-1;
340 for(from=0, to=nr-1; from<nr-min_nr; from++) {
341 ret=
llsqwt(x+from, y+from, (to-from)+1, wx+from, wy+from, 1.0E-10, w,
342 &lic, &lslope, &lnwss, NULL, NULL, NULL, NULL);
344 if(0) printf(
" range: %d-%d ; nwss=%g ; min=%g ; ret=%d\n", from, to, lnwss, nwss_min, ret);
345 if(ret==0 && lnwss<nwss_min) {nwss_min=lnwss; from_min=from; to_min=to;}
348 for(from=0, to=min_nr-1; to<nr; to++) {
349 ret=
llsqwt(x+from, y+from, (to-from)+1, wx+from, wy+from, 1.0E-10, w,
350 &lic, &lslope, &lnwss, NULL, NULL, NULL, NULL);
352 if(0) printf(
" range: %d-%d ; nwss=%g ; min=%g ; ret=%d\n", from, to, lnwss, nwss_min, ret);
353 if(ret==0 && lnwss<nwss_min) {nwss_min=lnwss; from_min=from; to_min=to;}
356 if(from_min<0) {free(w);
return(4);}
360 from=from_min; to=to_min;
361 ret=
llsqwt(x+from, y+from, (to-from)+1, wx+from, wy+from, 1.0E-15, w,
362 ic, slope, nwss, sic, sslope, cx+from, cy+from);
397 double qxx, qyy, qxy, mx, my, a, b, c, d, m1, m2, ssd1, ssd2;
399 if(0) {fprintf(stdout,
"llsqperp()\n"); fflush(stdout);}
401 if(nr<2 || x==NULL || y==NULL)
return(1);
403 for(i=0, mx=my=0; i<nr; i++) {mx+=x[i]; my+=y[i];}
404 mx/=(double)nr; my/=(double)nr;
406 for(i=0, qxx=qyy=qxy=0; i<nr; i++) {
407 a=x[i]-mx; b=y[i]-my; qxx+=a*a; qyy+=b*b; qxy+=a*b;
409 if(qxx<1.0E-100 || qyy<1.0E-100)
return(2);
411 a=qxy; b=qxx-qyy; c=-qxy;
414 fprintf(stdout,
"%d quadratic roots", rnr);
415 if(rnr>0) fprintf(stdout,
" %g", m1);
416 if(rnr>1) fprintf(stdout,
" %g", m2);
417 fprintf(stdout,
" ; traditional slope %g\n", qxy/qxx);
419 if(rnr==0)
return(3);
421 a=m1; b=-1; c=my-m1*mx;
422 for(i=0, ssd1=0; i<nr; i++) {
425 d=(a*x[i]+b*y[i]+c)/hypot(a, b);
430 a=m2; b=-1; c=my-m2*mx;
431 for(i=0, ssd2=0; i<nr; i++) {
434 d=(a*x[i]+b*y[i]+c)/hypot(a, b);
439 if(rnr==2 && ssd2<ssd1) {ssd1=ssd2; m1=m2;}
441 *slope=m1; *ic=my-m1*mx; *ssd=ssd1/(double)nr;
int llsqwt(double *x, double *y, int n, double *wx, double *wy, double tol, double *w, double *ic, double *slope, double *nwss, double *sic, double *sslope, double *cx, double *cy)
int best_llsqwt(double *x, double *y, double *wx, double *wy, int nr, int min_nr, int mode, double *slope, double *ic, double *nwss, double *sslope, double *sic, double *cx, double *cy, int *bnr)