TPCCLIB
Loading...
Searching...
No Matches
llsqwt.c File Reference

Linear least-squares fit with errors in both coordinates. More...

#include "libtpcmodel.h"

Go to the source code of this file.

Functions

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)
 
int llsqperp (double *x, double *y, int nr, double *slope, double *ic, double *ssd)
 
int llsqperp3 (double *x, double *y, int nr, double *slope, double *ic, double *ssd)
 
int quadratic (double a, double b, double c, double *m1, double *m2)
 
int medianline (double *x, double *y, int nr, double *slope, double *ic)
 

Detailed Description

Linear least-squares fit with errors in both coordinates.

Author
Vesa Oikonen

Definition in file llsqwt.c.

Function Documentation

◆ best_llsqwt()

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 )

Finds the best least-squares line to (x,y)-data, leaving points out either from the beginning (mode=0) or from the end (mode=1).

See also
llsqwt, llsqperp, medianline
Returns
Returns 0, if ok.
Parameters
xPlot x axis values.
yPlot y axis values.
wxWeighting factors for x.
wyWeighting factors for y.
nrNr of plot data points.
min_nrMin nr of points to use in the fit; must be >=4.
modeLeave out points from beginning (0) or from end (1).
slopeSlope is returned in here.
icY axis intercept is returned in here.
nwsssqrt(WSS)/wsum is returned here.
sslopeExpected sd of slope at calculated points.
sicExpected sd of intercept at calculated points.
cxCalculated x data points.
cyCalculated y data points.
bnrNumber of points in the best fit (incl data with w=0).

Definition at line 294 of file llsqwt.c.

325 {
326 int from, to, ret, from_min, to_min;
327 double *w, lic, lslope, lnwss=1.0E+100, nwss_min=1.0E+100;
328
329 /* Check the data */
330 if(x==NULL || y==NULL || nr<min_nr || nr<2) return(1);
331 /* Check parameters */
332 if(min_nr<4 || (mode!=0 && mode!=1)) return(2);
333
334 /* Make room for work vector */
335 w=(double*)malloc(nr*sizeof(double)); if(w==NULL) return(3);
336
337 /* Search the plot range that gives the best nwss */
338 nwss_min=9.99E+99; from_min=to_min=-1;
339 if(mode==0) { /* Leave out plot data from the beginning */
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);
343 /*lnwss/=(double)((to-from)+1);*/
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;}
346 }
347 } else { /* Leave out plot data from the end */
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);
351 /*lnwss/=(double)((to-from)+1);*/
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;}
354 }
355 }
356 if(from_min<0) {free(w); return(4);}
357
358 /* Run llsqwt() again with that range, now with better resolution */
359 /* and this time compute also SD's */
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);
363 free(w);
364 if(ret) return(5);
365 *bnr=(to-from)+1;
366
367 return(0);
368}
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)
Definition llsqwt.c:48

◆ llsqperp()

int llsqperp ( double * x,
double * y,
int nr,
double * slope,
double * ic,
double * ssd )

Simple non-iterative perpendicular line fitting. This function is fully based on the article [1].

References:

  1. Varga J & Szabo Z. Modified regression model for the Logan plot. J Cereb Blood Flow Metab 2002; 22:240-244.
See also
llsqperp3, medianline, llsqwt, mtga_best_perp
Returns
If successful, function returns value 0.
Parameters
xCoordinates of data points (dimension nr).
yCoordinates of data points (dimension nr).
nrNumber of data points.
slopeEstimated slope.
icEstimated intercept.
ssdSum of squared distances / nr.

Definition at line 382 of file llsqwt.c.

395 {
396 int i, rnr;
397 double qxx, qyy, qxy, mx, my, a, b, c, d, m1, m2, ssd1, ssd2;
398
399 if(0) {fprintf(stdout, "llsqperp()\n"); fflush(stdout);}
400 /* Check the data */
401 if(nr<2 || x==NULL || y==NULL) return(1);
402 /* Calculate the means */
403 for(i=0, mx=my=0; i<nr; i++) {mx+=x[i]; my+=y[i];}
404 mx/=(double)nr; my/=(double)nr;
405 /* Calculate the Q's */
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;
408 }
409 if(qxx<1.0E-100 || qyy<1.0E-100) return(2);
410 /* Calculate the slope as real roots of quadratic equation */
411 a=qxy; b=qxx-qyy; c=-qxy;
412 rnr=quadratic(a, b, c, &m1, &m2);
413 if(0) {
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);
418 }
419 if(rnr==0) return(3);
420 /* Calculate the sum of squared distances for the first root */
421 a=m1; b=-1; c=my-m1*mx;
422 for(i=0, ssd1=0; i<nr; i++) {
423 /* calculate the distance from point (x[i],y[i]) to line ax+by+c=0 */
424 //d=(a*x[i]+b*y[i]+c)/sqrt(a*a+b*b);
425 d=(a*x[i]+b*y[i]+c)/hypot(a, b);
426 ssd1+=d*d;
427 }
428 /* Also to the 2nd root, if there is one */
429 if(rnr==2) {
430 a=m2; b=-1; c=my-m2*mx;
431 for(i=0, ssd2=0; i<nr; i++) {
432 /* calculate the distance from point (x[i],y[i]) to line ax+by+c=0 */
433 //d=(a*x[i]+b*y[i]+c)/sqrt(a*a+b*b);
434 d=(a*x[i]+b*y[i]+c)/hypot(a, b);
435 ssd2+=d*d;
436 }
437 } else ssd2=ssd1;
438 /* If there were 2 roots, select the one with smaller ssd */
439 if(rnr==2 && ssd2<ssd1) {ssd1=ssd2; m1=m2;}
440 /* Set the slope and intercept */
441 *slope=m1; *ic=my-m1*mx; *ssd=ssd1/(double)nr;
442
443 return(0);
444}
int quadratic(double a, double b, double c, double *m1, double *m2)
Definition llsqwt.c:490

Referenced by img_logan(), img_patlak(), llsqperp3(), and mtga_best_perp().

◆ llsqperp3()

int llsqperp3 ( double * x,
double * y,
int nr,
double * slope,
double * ic,
double * ssd )

Simple non-iterative perpendicular line fitting. This version of the function accepts data that contains NaN's.

See also
llsqperp, medianline
Returns
If successful, function returns value 0.
Parameters
xCoordinates of data points (dimension nr).
yCoordinates of data points (dimension nr).
nrNumber of data points.
slopeEstimated slope.
icEstimated intercept.
ssdSum of squared distances / nr.

Definition at line 453 of file llsqwt.c.

466 {
467 int i, j;
468 double *nx, *ny;
469
470 /* Allocate memory for new data pointers */
471 nx=(double*)calloc(nr, sizeof(double)); if(nx==NULL) return 1;
472 ny=(double*)calloc(nr, sizeof(double));
473 if(ny==NULL) {free((char*)nx); return 1;}
474
475 /* Copy data to pointers */
476 for(i=0, j=0; i<nr; i++)
477 if(!isnan(x[i]) && !isnan(y[i])) {nx[j]=x[i]; ny[j]=y[i]; j++;}
478
479 /* Use llsqperp() */
480 i=llsqperp(nx, ny, j, slope, ic, ssd);
481 free((char*)nx); free((char*)ny);
482 return(i);
483}
int llsqperp(double *x, double *y, int nr, double *slope, double *ic, double *ssd)
Definition llsqwt.c:382

◆ llsqwt()

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 )

Iterative method for linear least-squares fit with errors in both coordinates.

This function is fully based on article [3].

For n data-point pairs (x[i], y[i]) each point has its own weighting factors in (wx[i], wy[i]). This routine finds the values of the parameters m (slope) and c (intercept, ic) that yield the "best-fit" of the model equation Y = mX + c to the data, where X and Y are the predicted or calculated values of the data points.

Weighting factors wx and wy must be assigned as the inverses of the variances or squares of the measurement uncertainties (SDs), i.e. w[i]=1/(sd[i])^2

If true weights are unknown but yet the relative weights are correct, the slope, intercept and residuals (WSS) will be correct. The applied term S/(N-2) makes also the estimate of sigma (sd) of slope less dependent on the scaling of weights. The sigmas are not exact, since only the lowest-order terms in Taylor-series expansion are incorporated; anyhow sigmas are more accurate than the ones based on York algorithm.

One or more data points can be excluded from the fit by setting either x or y weight to 0.

References:

  1. York, D. Linear-squares fitting of a straight line. Can J Phys. 1966;44:1079-1086.
  2. Lybanon, M. A better least squares method when both variables have uncertainties. Am J Phys. 1984;52:22-26 and 276-278.
  3. Reed BC. Linear least-squares fits with errors in both coordinates. II: Comments on parameter variances. Am J Phys. 1992;60:59-62.
See also
llsqperp, best_llsqwt, medianline
Returns
If successful, function returns value 0.
Parameters
xcoordinates of data points (of dimension n).
ycoordinates of data points (of dimension n).
nnumber of data points.
wxweighting factors in x.
wyweighting factors in y.
tolallowed tolerance in slope estimation.
wwork vector (of dimension n); effective weights w[i] are returned in it.
icEstimated intercept.
slopeEstimated slope.
nwsssqrt(WSS)/wsum of the residuals.
sicexpected sd of intercept at calculated points; If NULL, then not calculated and variable is left unchanged.
sslopeExpected sd of slope at calculated points; If NULL, then not calculated and variable is left unchanged.
cxEstimated data points (X,y); If NULL, then not calculated and variable is left unchanged.
cyEstimated data points (x,Y); If NULL, then not calculated and variable is left unchanged.

Definition at line 48 of file llsqwt.c.

83 {
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;
90
91
92 /*
93 * Lets look what we got for arguments
94 */
95 if(0) {fprintf(stdout, "llsqwt()\n"); fflush(stdout);}
96 /* Check that there is some data */
97 if(n<2) return(1);
98 if(0) {
99 for(i=0; i<n; i++) printf("%e +- %e %e +- %e\n",
100 x[i], wx[i], y[i], wy[i]);
101 }
102 if(tol<1.0e-100) return(1);
103 if(w==NULL) return(1);
104 /* Check if variances and fitted data will be calculated */
105 if(sic==NULL || sslope==NULL || cx==NULL || cy==NULL) calcVar=0;
106 else calcVar=1;
107
108 /* If only 2 datapoints */
109 if(n==2) {
110 f=x[1]-x[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;
114 return(0);
115 }
116
117 /*
118 * Fit the LLSQ line
119 */
120
121 /* First estimation of the slope and intercept by unweighted regression */
122 for(i=0; i<n; i++) {
123 xsum+=x[i]; ysum+=y[i]; x2sum+=x[i]*x[i]; xysum+=x[i]*y[i];
124 }
125 delta=(double)n*x2sum - xsum*xsum;
126 /* Initial guesses of the slope and intercept */
127 if(delta==0.0) {
128 if(0) printf("x axis values contain only zeroes.\n");
129 *slope=*ic=*sic=*sslope=*nwss=w[0]=w[1]=0.0;
130 return(0);
131 }
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);
135
136 /* Begin the iterations */
137 bcont=m+2.0*tol;
138 while(fabs(m-bcont)>tol && niter<20) {
139 if(0) printf(" %d. iteration, improvement=%g, tol=%g\n", niter, fabs(m-bcont), tol);
140 bcont=m; niter++;
141 /* Compute the weighting factors */
142 m2=m*m;
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++;}
146 //printf("wx[i]=%g wy[i]=%g -> w[%d]=%g\n", wx[i], wy[i], i, w[i]);
147 }
148 if(nn<2) {
149 if(0) printf("less than two points with weight > 0.\n");
150 *slope=*ic=*sic=*sslope=*nwss=0.0;
151 return(0);
152 }
153 /* Compute the barycentre coordinates */
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);
156 xb/=wsum; yb/=wsum;
157 if(0) printf("barycentre: xb=%g yb=%g\n", xb, yb);
158 /* Estimate the slope as either of the roots of the quadratic */
159 /* compute the coefficients of the quadratic */
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];
162 qa += w2*u*v/wx[i];
163 qb += w2*(u*u/wy[i] - v*v/wx[i]);
164 qc += -w2*u*v/wy[i];
165 }
166 if(0) printf("quadratic coefs: qa=%g qb=%g qc=%g\n", qa, qb, qc);
167 if(qa==0.0) {
168 m=0.0;
169 /* Calculate WSS */
170 for(i=0, ss=0.0; i<n; i++) {f=v=y[i]-yb; ss+=w[i]*f*f;}
171 } else if(qa==1.0) { /* check if quadratic reduces to a linear form */
172 m=-qc/qb;
173 /* Calculate WSS */
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;}
175 } else {
176 /* discriminant of quadratic */
177 discr=qb*qb-4.0*qa*qc; if(discr<=0.0) sqdis=0.0; else sqdis=sqrt(discr);
178 /* compute the two solutions of quadratic */
179 m_1=(-qb+sqdis)/(2.0*qa); m_2=(-qb-sqdis)/(2.0*qa);
180 /* Calculate WSS for both solutions */
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;
185 }
186 /* choose the solution with lower WSS */
187 if(s1<=s2) {m=m_1; ss=s1;} else {m=m_2; ss=s2;}
188 }
189 /* Calculate the intercept */
190 c = yb - m*xb;
191 if(0) printf("iterated parameters: c=%e m=%e\n", c, m);
192
193 } /* end of iteration loop */
194 *ic=c; *slope=m; *nwss=sqrt(ss)/wsum; /* Set function return values */
195 if(0) {
196 fprintf(stdout, "c=%14.7e m=%14.7e ss=%14.7e niter=%d\n", c, m, ss, niter);
197 }
198
199 /* Return here, if variances are not to be calculated */
200 if(!calcVar) return(0);
201
202 /*
203 * Calculate the fitted line
204 */
205 for(i=0; i<n; i++) {
206 if(w[i]>0.0) {
207 f=w[i]*(c + m*x[i] - y[i]); /* Lagrangian multiplier */
208 cx[i]=x[i]-f*m/wx[i]; cy[i]=y[i]+f/wy[i];
209 } else {
210 cx[i]=x[i]; cy[i]=y[i];
211 }
212 }
213
214 /*
215 * Estimate the variances of the parameters (Reed 1992)
216 */
217 /* varm = var of slope ; varc = var of intercept */
218
219 /* Use the true nr of data points, i.e. exclude the ones with zero weight */
220 for(i=nn=0; i<n; i++) if(w[i]>0.0) nn++;
221 if(nn<3) {*sslope=*sic=0.0; return(0);}
222
223 /* Compute the barycentre coordinates again from computed data points */
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);
226 xb/=wsum; yb/=wsum;
227 if(0) printf("barycentre: xb=%g yb=%g\n", xb, yb);
228
229 /* common factors */
230 HH=JJ=qa=qb=qc=0.0;
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];
233 qa += w2*u*v/wx[i];
234 qb += w2*(u*u/wy[i] - v*v/wx[i]);
235 qc += -w2*u*v/wy[i];
236 HH += w2*v/wx[i];
237 JJ += w2*u/wx[i];
238 }
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);
241 AA=BB=CC=0.0;
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);
247 }
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);
250 /* sigmas */
251 varc=varm=0.0;
252 for(j=0; j<n; j++) if(w[j]>0.0) {
253 /* factors for this j */
254 DD=EE=FF=GG=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; /* Kronecker delta */
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;
263 }
264 EE*=2.0;
265 /* derivatives at jth data point */
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;
271 /* sum terms for sigmas */
272 varm += dmy*dmy/wy[j] + dmx*dmx/wx[j];
273 varc += dcy*dcy/wy[j] + dcx*dcx/wx[j];
274 if(0)
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);
277 }
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);
282 *sic = sqrt(varc);
283 if(0) {fprintf(stdout, "sslope=%14.7e sic=%14.7e\n", *sslope, *sic);}
284 return(0);
285}

Referenced by best_llsqwt(), and best_logan_reed().

◆ medianline()

int medianline ( double * x,
double * y,
int nr,
double * slope,
double * ic )

Median-based distribution-free estimation of slope and intercept. This method has no need for weighting and is insensitive to outliers. Note that this is not LMS !

Reference (containing reference to the original idea):

  1. Siegel AF. Robust regression using repeated medians. Biometrika 1982;69(1):242-244.
See also
llsqperp
Returns
If successful, function returns value 0.
Parameters
xCoordinates of data points (dimension nr).
yCoordinates of data points (dimension nr).
nrNumber of data points.
slopeEstimated slope.
icEstimated intercept.

Definition at line 533 of file llsqwt.c.

544 {
545 int i, j, snr;
546 double *sp, *ip, d;
547
548 if(0) fprintf(stdout, "medianline()\n");
549 /* Check the data */
550 if(nr<2 || x==NULL || y==NULL) return(1);
551 /* Allocate memory for slopes and intercepts */
552 for(i=0, snr=0; i<nr-1; i++) for(j=i+1; j<nr; j++) snr++;
553 sp=(double*)malloc(snr*sizeof(double));
554 ip=(double*)malloc(snr*sizeof(double));
555 if(sp==NULL || ip==NULL) return(2);
556 /* Calculate the slopes and intercepts */
557 for(i=0, snr=0; i<nr-1; i++) for(j=i+1; j<nr; j++) {
558 if(isnan(x[i]) || isnan(x[j]) || isnan(y[i]) || isnan(y[j])) continue;
559 d=x[j]-x[i]; if(d==0) continue;
560 sp[snr]=(y[j]-y[i])/d; ip[snr]=y[i]-sp[snr]*x[i];
561 snr++;
562 }
563 if(snr<2) {free(sp); free(ip); return(3);}
564 /* Get the medians of slope and intercept */
565 qsort(sp, snr, sizeof(double), _medianline_cmp);
566 qsort(ip, snr, sizeof(double), _medianline_cmp);
567 if(snr%2==1) {*slope=sp[snr/2]; *ic=ip[snr/2];}
568 else {*slope=0.5*(sp[snr/2]+sp[(snr/2)-1]); *ic=0.5*(ip[snr/2]+ip[(snr/2)-1]);}
569 free(sp); free(ip);
570 return(0);
571}

◆ quadratic()

int quadratic ( double a,
double b,
double c,
double * m1,
double * m2 )

Finds the real roots of a*x^2 + b*x + c = 0

Returns
Returns the nr of roots, and the roots in m1 and m2.
Parameters
aInput A
bInput B
cInput C
m1Output: Root 1
m2Output: Root 2

Definition at line 490 of file llsqwt.c.

501 {
502 double discriminant, r, r1, r2, sgnb, temp;
503
504 if(a==0) {if(b==0) return(0); else {*m1=*m2=-c/b; return(1);}}
505 discriminant=b*b - 4*a*c;
506 if(discriminant>0) {
507 if(b==0) {r=fabs(0.5*sqrt(discriminant)/a); *m1=-r; *m2=r;}
508 else {
509 sgnb=(b>0 ? 1:-1); temp=-0.5*(b + sgnb*sqrt(discriminant));
510 r1=temp/a; r2=c/temp; if(r1<r2) {*m1=r1; *m2=r2;} else {*m1=r2; *m2=r1;}
511 }
512 return(2);
513 } else if(discriminant==0) {
514 *m1=-0.5*b/a; *m2=-0.5*b/a;
515 return(2);
516 } else {
517 return(0);
518 }
519}

Referenced by llsqperp().