SDDSlib
Loading...
Searching...
No Matches
lsfn.c File Reference

Computes nth order polynomial least squares fit. More...

#include "matlib.h"
#include "mdb.h"

Go to the source code of this file.

Functions

int p_merror (char *message)
 
long lsfn (double *xd, double *yd, double *sy, long nd, long nf, double *coef, double *s_coef, double *chi, double *diff)
 Computes nth order polynomial least squares fit.
 

Detailed Description

Computes nth order polynomial least squares fit.

This file contains the implementation of the lsfn function, which computes a polynomial least squares fit of a specified order to given data points. It supports both weighted and unweighted fitting.

Author: Michael Borland, 1986.

Definition in file lsfn.c.

Function Documentation

◆ lsfn()

long lsfn ( double * xd,
double * yd,
double * sy,
long nd,
long nf,
double * coef,
double * s_coef,
double * chi,
double * diff )

Computes nth order polynomial least squares fit.

This function performs an nth order polynomial least squares fit to the provided data. It supports both weighted and unweighted fitting based on the standard deviations provided.

Parameters
xdArray of x data points.
ydArray of y data points.
syArray of standard deviations of y data points. If NULL or all elements are equal, an unweighted fit is performed.
ndNumber of data points.
nfOrder of the polynomial fit (degree of the polynomial).
coefArray to store the computed coefficients of the polynomial.
s_coefArray to store the standard deviations of the coefficients.
chiPointer to store the reduced chi-squared value. If NULL, chi-squared is not computed.
diffArray to store the differences between fitted and actual y values. If NULL, differences are not stored.
Returns
Returns 1 on success, or 0 on error.

Definition at line 34 of file lsfn.c.

41 {
42 long i, j, nt, unweighted;
43 double xp, *x_i, x0;
44 static MATRIX *X, *Y, *Yp, *C, *C_1, *Xt, *A, *Ca, *XtC, *XtCX, *T, *Tt, *TC;
45
46 nt = nf + 1;
47 if (nd < nt) {
48 printf("error: insufficient data for requested order of fit\n");
49 printf("(%ld data points, %ld terms in fit)\n", nd, nt);
50 exit(1);
51 }
52
53 unweighted = 1;
54 if (sy)
55 for (i = 1; i < nd; i++)
56 if (sy[i] != sy[0]) {
57 unweighted = 0;
58 break;
59 }
60
61 /* allocate matrices */
62 m_alloc(&X, nd, nt);
63 m_alloc(&Y, nd, 1);
64 m_alloc(&Yp, nd, 1);
65 m_alloc(&Xt, nt, nd);
66 if (!unweighted) {
67 m_alloc(&C, nd, nd);
68 m_alloc(&C_1, nd, nd);
69 m_zero(C);
70 m_zero(C_1);
71 }
72 m_alloc(&A, nt, 1);
73 m_alloc(&Ca, nt, nt);
74 m_alloc(&XtC, nt, nd);
75 m_alloc(&XtCX, nt, nt);
76 m_alloc(&T, nt, nd);
77 m_alloc(&Tt, nd, nt);
78 m_alloc(&TC, nt, nd);
79
80 /* Compute X, Y, C, C_1. X[i][j] = (xd[i])^j. Y[i][0] = yd[i].
81 * C = delta(i,j)*sy[i]^2 (covariance matrix of yd)
82 * C_1 = INV(C)
83 */
84 for (i = 0; i < nd; i++) {
85 x_i = X->a[i];
86 x0 = xd[i];
87 xp = 1.0;
88 Y->a[i][0] = yd[i];
89 if (!unweighted) {
90 C->a[i][i] = sqr(sy[i]);
91 C_1->a[i][i] = 1 / C->a[i][i];
92 }
93 for (j = 0; j < nt; j++) {
94 x_i[j] = xp;
95 xp *= x0;
96 }
97 }
98
99 /* Compute A, the matrix of coefficients.
100 * Weighted least-squares solution is A = INV(Xt.INV(C).X).Xt.INV(C).y
101 * Unweighted solution is A = INV(Xt.X).Xt.y
102 */
103 if (unweighted) {
104 /* eliminating 2 matrix operations makes this much faster than a weighted fit
105 * if there are many data points.
106 */
107 if (!m_trans(Xt, X))
108 return (p_merror("transposing X"));
109 if (!m_mult(XtCX, Xt, X))
110 return (p_merror("multiplying Xt.X"));
111 if (!m_invert(XtCX, XtCX))
112 return (p_merror("inverting XtCX"));
113 if (!m_mult(T, XtCX, Xt))
114 return (p_merror("multiplying XtX.Xt"));
115 if (!m_mult(A, T, Y))
116 return (p_merror("multiplying T.Y"));
117
118 /* Compute covariance matrix of A, Ca = (T.Tt)*C[0][0] */
119 if (!m_trans(Tt, T))
120 return (p_merror("computing transpose of T"));
121 if (!m_mult(Ca, T, Tt))
122 return (p_merror("multiplying T.Tt"));
123 if (!m_scmul(Ca, Ca, sy ? sqr(sy[0]) : 1))
124 return (p_merror("multiplying T.Tt by scalar"));
125 } else {
126 if (!m_trans(Xt, X))
127 return (p_merror("transposing X"));
128 if (!m_mult(XtC, Xt, C_1))
129 return (p_merror("multiplying Xt.C_1"));
130 if (!m_mult(XtCX, XtC, X))
131 return (p_merror("multiplying XtC.X"));
132 if (!m_invert(XtCX, XtCX))
133 return (p_merror("inverting XtCX"));
134 if (!m_mult(T, XtCX, XtC))
135 return (p_merror("multiplying XtCX.XtC"));
136 if (!m_mult(A, T, Y))
137 return (p_merror("multiplying T.Y"));
138
139 /* Compute covariance matrix of A, Ca = T.C.Tt */
140 if (!m_mult(TC, T, C))
141 return (p_merror("multiplying T.C"));
142 if (!m_trans(Tt, T))
143 return (p_merror("computing transpose of T"));
144 if (!m_mult(Ca, TC, Tt))
145 return (p_merror("multiplying TC.Tt"));
146 }
147
148 for (i = 0; i < nt; i++) {
149 coef[i] = A->a[i][0];
150 if (s_coef)
151 s_coef[i] = sqrt(Ca->a[i][i]);
152 }
153
154 /* Compute Yp = X.A, use to compute chi-squared */
155 if (chi) {
156 if (!m_mult(Yp, X, A))
157 return (p_merror("multiplying X.A"));
158 *chi = 0;
159 for (i = 0; i < nd; i++) {
160 xp = (Yp->a[i][0] - yd[i]);
161 if (diff != NULL)
162 diff[i] = xp;
163 xp /= sy ? sy[i] : 1;
164 *chi += xp * xp;
165 }
166 if (nd != nt)
167 *chi /= (nd - nt);
168 }
169
170 m_free(&X);
171 m_free(&Y);
172 m_free(&Yp);
173 m_free(&Xt);
174 if (!unweighted) {
175 m_free(&C);
176 m_free(&C_1);
177 }
178 m_free(&A);
179 m_free(&Ca);
180 m_free(&XtC);
181 m_free(&XtCX);
182 m_free(&T);
183 m_free(&Tt);
184 m_free(&TC);
185 return (1);
186}