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.
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
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
81
82
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
100
101
102
103 if (unweighted) {
104
105
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
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
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
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}