4 #include <gsl/gsl_bspline.h>
5 #include <gsl/gsl_multifit.h>
6 #include <gsl/gsl_rng.h>
7 #include <gsl/gsl_randist.h>
8 #include <gsl/gsl_statistics.h>
10 /* number of data points to fit */
13 /* number of fit coefficients */
16 /* nbreak = ncoeffs + 2 - k = ncoeffs - 2 since k = 4 */
17 #define NBREAK (NCOEFFS - 2)
23 const size_t ncoeffs = NCOEFFS;
24 const size_t nbreak = NBREAK;
26 gsl_bspline_workspace *bw;
33 gsl_multifit_linear_workspace *mw;
39 r = gsl_rng_alloc(gsl_rng_default);
41 /* allocate a cubic bspline workspace (k = 4) */
42 bw = gsl_bspline_alloc(4, nbreak);
43 B = gsl_vector_alloc(ncoeffs);
45 x = gsl_vector_alloc(n);
46 y = gsl_vector_alloc(n);
47 X = gsl_matrix_alloc(n, ncoeffs);
48 c = gsl_vector_alloc(ncoeffs);
49 w = gsl_vector_alloc(n);
50 cov = gsl_matrix_alloc(ncoeffs, ncoeffs);
51 mw = gsl_multifit_linear_alloc(n, ncoeffs);
54 /* this is the data to be fitted */
55 for (i = 0; i < n; ++i)
58 double xi = (15.0 / (N - 1)) * i;
59 double yi = cos(xi) * exp(-0.1 * xi);
62 dy = gsl_ran_gaussian(r, sigma);
65 gsl_vector_set(x, i, xi);
66 gsl_vector_set(y, i, yi);
67 gsl_vector_set(w, i, 1.0 / (sigma * sigma));
69 printf("%f %f\n", xi, yi);
72 /* use uniform breakpoints on [0, 15] */
73 gsl_bspline_knots_uniform(0.0, 15.0, bw);
75 /* construct the fit matrix X */
76 for (i = 0; i < n; ++i)
78 double xi = gsl_vector_get(x, i);
80 /* compute B_j(xi) for all j */
81 gsl_bspline_eval(xi, B, bw);
83 /* fill in row i of X */
84 for (j = 0; j < ncoeffs; ++j)
86 double Bj = gsl_vector_get(B, j);
87 gsl_matrix_set(X, i, j, Bj);
92 gsl_multifit_wlinear(X, w, y, c, cov, &chisq, mw);
95 Rsq = 1.0 - chisq / gsl_stats_wtss(w->data, 1, y->data, 1, y->size);
97 fprintf(stderr, "chisq/dof = %e, Rsq = %f\n", chisq / dof, Rsq);
99 /* output the smoothed curve */
103 printf("#m=1,S=0\n");
104 for (xi = 0.0; xi < 15.0; xi += 0.1)
106 gsl_bspline_eval(xi, B, bw);
107 gsl_multifit_linear_est(B, c, cov, &yi, &yerr);
108 printf("%f %f\n", xi, yi);
113 gsl_bspline_free(bw);
120 gsl_matrix_free(cov);
121 gsl_multifit_linear_free(mw);