SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
lsfp.c File Reference

Detailed Description

Polynomial least squares fit using specified terms.

Implements the lsfp routine that computes an nth order polynomial least squares fit using only the terms requested by the caller.

Michael Borland, 1986.

Definition in file lsfp.c.

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

Go to the source code of this file.

Functions

int p_merror (char *message)
 
long lsfp (double *xd, double *yd, double *sy, long n_pts, long n_terms, long *power, double *coef, double *s_coef, double *chi, double *diff)
 

Function Documentation

◆ lsfp()

long lsfp ( double * xd,
double * yd,
double * sy,
long n_pts,
long n_terms,
long * power,
double * coef,
double * s_coef,
double * chi,
double * diff )

Definition at line 15 of file lsfp.c.

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