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

Computes generalized least squares fits using a function passed by the caller. More...

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

Go to the source code of this file.

Functions

int p_merror (char *message)
 
long lsfg (double *xd, double *yd, double *sy, long n_pts, long n_terms, int32_t *order, double *coef, double *s_coef, double *chi, double *diff, double(*fn)(double x, long ord))
 Computes generalized least squares fits using a function passed by the caller.
 

Detailed Description

Computes generalized least squares fits using a function passed by the caller.

This file contains the implementation of the lsfg() function, which performs generalized least squares fitting using user-provided basis functions. It also declares the p_merror() function for handling matrix errors.

Michael Borland, 1986.

Definition in file lsfg.c.

Function Documentation

◆ lsfg()

long lsfg ( double * xd,
double * yd,
double * sy,
long n_pts,
long n_terms,
int32_t * order,
double * coef,
double * s_coef,
double * chi,
double * diff,
double(* fn )(double x, long ord) )

Computes generalized least squares fits using a function passed by the caller.

Parameters
xdArray of x-data points.
ydArray of y-data points.
syArray of standard deviations for y-data points. If NULL, an unweighted fit is performed.
n_ptsNumber of data points.
n_termsNumber of terms in the fit.
orderArray specifying the order for each term.
coefOutput array to store the coefficients of the fit.
s_coefOutput array to store the standard deviations of the coefficients.
chiOutput pointer to store the reduced chi-squared value.
diffOutput array to store the differences between observed and fitted y-values.
fnFunction pointer to the basis function.
Returns
Returns 1 on success, 0 on failure.

Definition at line 30 of file lsfg.c.

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