6 void sgram_(double *sg0, double *sg1, double *sg2,
7 double *sg3, double* knot, int* nk);
8 void stxwx_(double *xs, double *ys, double *ws, int *n,
9 double *knot, int *nk, double *xwy, double *hs0, double *hs1, double *hs2, double *hs3);
10 void sslvrg_(double *penalt, double *dofoff, double *xs, double *ys, double *ws, double *ssw, int *n,
11 double *knot, int *nk,
12 double *coef, double *sz, double *lev, double *crit, int *icrit, double *lspar, double *xwy,
13 double *hs0, double *hs1, double *hs2, double *hs3,
14 double *sg0, double *sg1, double *sg2, double *sg3, double *abd,
15 double *p1ip, double *p2ip, int *ld4, int *ldnk, int *ier);
17 /***********************************************************/
18 // used as reference - http://www.koders.com/fortran/fid8AA63B49CF22F0138E9B3DBDC405696F4A62C1CF.aspx
19 // http://www.koders.com/c/fidD995301A8A5549CE0361F4E7FFDFD3CDC4B4E4A3.aspx
20 /* A Cubic B-spline Smoothing routine.
22 // sbart.f -- translated by f2c (version 20010821).
23 // ------- and f2c-clean,v 1.9 2000/01/13
25 // According to the GAMFIT sources, this was derived from code by
26 // Finbarr O'Sullivan.
30 The algorithm minimises:
32 (1/n) * sum ws(i)^2 * (ys(i)-sz(i))^2 + lambda* int ( s"(x) )^2 dx
34 lambda is a function of the spar which is assumed to be between 0 and 1
38 penalt A penalty > 1 to be used in the gcv criterion
39 dofoff either `df.offset' for GCV or `df' (to be matched).
40 n number of data points
41 ys(n) vector of length n containing the observations
42 ws(n) vector containing the weights given to each data point
43 NB: the code alters the values here.
44 xs(n) vector containing the ordinates of the observations
45 ssw `centered weighted sum of y^2'
46 nk number of b-spline coefficients to be estimated
48 knot(nk+4) vector of knot points defining the cubic b-spline basis.
49 To obtain full cubic smoothing splines one might
50 have (provided the xs-values are strictly increasing)
51 spar penalised likelihood smoothing parameter
52 ispar indicating if spar is supplied (ispar=1) or to be estimated
53 lspar, uspar lower and upper values for spar search; 0.,1. are good values
54 tol, eps used in Golden Search routine
55 isetup setup indicator [initially 0
56 icrit indicator saying which cross validation score is to be computed
57 0: none ; 1: GCV ; 2: CV ; 3: 'df matching'
58 ld4 the leading dimension of abd (ie ld4=4)
59 ldnk the leading dimension of p2ip (not referenced)
63 coef(nk) vector of spline coefficients
64 sz(n) vector of smoothed z-values
65 lev(n) vector of leverages
66 crit either ordinary or generalized CV score
68 lspar == lambda (a function of spar and the design)
69 iter number of iterations needed for spar search (if ispar != 1)
71 ier = 0 ___ everything fine
72 ier = 1 ___ spar too small or too big
73 problem in cholesky decomposition
77 hs0,hs1,hs2,hs3 the diagonals of the X'WX matrix
78 sg0,sg1,sg2,sg3 the diagonals of the Gram matrix SIGMA
79 abd (ld4,nk) [ X'WX + lambda*SIGMA ] in diagonal form
80 p1ip(ld4,nk) inner products between columns of L inverse
81 p2ip(ldnk,nk) all inner products between columns of L inverse
82 where L'L = [X'WX + lambda*SIGMA] NOT REFERENCED
86 (double *penalt, double *dofoff,
87 double *xs, double *ys, double *ws, double *ssw,
88 int *n, double *knot, int *nk, double *coef,
89 double *sz, double *lev, double *crit, int *icrit,
90 double *spar, int *ispar, int *iter, double *lspar,
91 double *uspar, double *tol, double *eps, int *isetup,
92 int *ld4, int *ldnk, int *ier)
95 /* A Cubic B-spline Smoothing routine.
97 The algorithm minimises:
99 (1/n) * sum ws(i)^2 * (ys(i)-sz(i))^2 + lambda* int ( s(x) )^2 dx
101 lambda is a function of the spar which is assumed to be between 0 and 1
105 penalt A penalty > 1 to be used in the gcv criterion
106 dofoff either `df.offset' for GCV or `df' (to be matched).
107 n number of data points
108 ys(n) vector of length n containing the observations
109 ws(n) vector containing the weights given to each data point
110 NB: the code alters the values here.
111 xs(n) vector containing the ordinates of the observations
112 ssw `centered weighted sum of y^2
113 nk number of b-spline coefficients to be estimated
115 knot(nk+4) vector of knot points defining the cubic b-spline basis.
116 To obtain full cubic smoothing splines one might
117 have (provided the xs-values are strictly increasing)
118 spar penalised likelihood smoothing parameter
119 ispar indicating if spar is supplied (ispar=1) or to be estimated
120 lspar, uspar lower and upper values for spar search; 0.,1. are good values
121 tol, eps used in Golden Search routine
122 isetup setup indicator [initially 0
123 icrit indicator saying which cross validation score is to be computed
124 0: none ; 1: GCV ; 2: CV ; 3: 'df matching'
125 ld4 the leading dimension of abd (ie ld4=4)
126 ldnk the leading dimension of p2ip (not referenced)
130 coef(nk) vector of spline coefficients
131 sz(n) vector of smoothed z-values
132 lev(n) vector of leverages
133 crit either ordinary or generalized CV score
135 lspar == lambda (a function of spar and the design)
136 iter number of iterations needed for spar search (if ispar != 1)
138 ier = 0 ___ everything fine
139 ier = 1 ___ spar too small or too big
140 problem in cholesky decomposition
142 Working arrays/matrix
144 hs0,hs1,hs2,hs3 the diagonals of the XWX matrix
145 sg0,sg1,sg2,sg3 the diagonals of the Gram matrix SIGMA
146 abd (ld4,nk) [ XWX + lambda*SIGMA ] in diagonal form
147 p1ip(ld4,nk) inner products between columns of L inverse
148 p2ip(ldnk,nk) all inner products between columns of L inverse
149 where LL = [XWX + lambda*SIGMA] NOT REFERENCED
152 #define CRIT(FX) (*icrit == 3 ? FX - 3. : FX)
153 /* cancellation in (3 + eps) - 3, but still...informative */
155 #define BIG_f (1e100)
157 /* c_Gold is the squared inverse of the golden ratio */
158 static const double c_Gold = 0.381966011250105151795413165634;
159 /* == (3. - sqrt(5.)) / 2. */
161 /* Local variables */
162 static double ratio;/* must be static (not needed in R) */
164 double a, b, d, e, p, q, r, u, v, w, x;
165 double ax, fu, fv, fw, fx, bx, xm;
166 double t1, t2, tol1, tol2;
167 double* xwy = new double[*nk];
168 double* hs0 = new double[*nk];
169 double* hs1 = new double[*nk];
170 double* hs2 = new double[*nk];
171 double* hs3 = new double[*nk];
172 double* sg0 = new double[*nk];
173 double* sg1 = new double[*nk];
174 double* sg2 = new double[*nk];
175 double* sg3 = new double[*nk];
176 double* abd = new double[*nk*(*ld4)];
177 double* p1ip = new double[*nk*(*ld4)];
178 double* p2ip = new double[*nk];
181 /* unnecessary initializations to keep -Wall happy */
182 d = 0.; fu = 0.; u = 0.;
185 /* Compute SIGMA, X' W X, X' W z, trace ratio, s0, s1.
187 SIGMA -> sg0,sg1,sg2,sg3
188 X' W X -> hs0,hs1,hs2,hs3
192 /* trevor fixed this 4/19/88
193 * Note: sbart, i.e. stxwx() and sslvrg() {mostly, not always!}, use
194 * the square of the weights; the following rectifies that */
195 for (i = 0; i < *n; ++i)
200 /* SIGMA[i,j] := Int B''(i,t) B''(j,t) dt {B(k,.) = k-th B-spline} */
201 sgram_(sg0, sg1, sg2, sg3, knot, nk);
202 stxwx_(xs, ys, ws, n,
206 /* Compute ratio := tr(X' W X) / tr(SIGMA) */
208 for (i = 3 - 1; i < (*nk - 3); ++i) {
215 /* Compute estimate */
217 if (*ispar == 1) { /* Value of spar supplied */
218 *lspar = ratio * pow(16.0, (*spar * 6.0 - 2.0));
219 sslvrg_(penalt, dofoff, xs, ys, ws, ssw, n,
221 coef, sz, lev, crit, icrit, lspar, xwy,
223 sg0, sg1, sg2, sg3, abd,
224 p1ip, p2ip, ld4, ldnk, ier);
225 /* got through check 2 */
229 /* ELSE ---- spar not supplied --> compute it ! ---------------------------
231 Use Forsythe Malcom and Moler routine to MINIMIZE criterion
232 f denotes the value of the criterion
234 an approximation x to the point where f attains a minimum on
235 the interval (ax,bx) is determined.
242 ax left endpoint of initial interval
243 bx right endpoint of initial interval
244 f function subprogram which evaluates f(x) for any x
245 in the interval (ax,bx)
246 tol desired length of the interval of uncertainty of the final
251 fmin abcissa approximating the point where f attains a minimum
255 The method used is a combination of golden section search and
256 successive parabolic interpolation. convergence is never much slower
257 than that for a fibonacci search. if f has a continuous second
258 derivative which is positive at the minimum (which is not at ax or
259 bx), then convergence is superlinear, and usually of the order of
261 the function f is never evaluated at two points closer together
262 than eps*abs(fmin) + (tol/3), where eps is approximately the square
263 root of the relative machine precision. if f is a unimodal
264 function and the computed values of f are always unimodal when
265 separated by at least eps*abs(x) + (tol/3), then fmin approximates
266 the abcissa of the global minimum of f on the interval ax,bx with
267 an error less than 3*eps*abs(fmin) + tol. if f is not unimodal,
268 then fmin may approximate a local, but perhaps non-global, minimum to
270 this function subprogram is a slightly modified version of the
271 algol 60 procedure localmin given in richard brent, algorithms for
272 minimization without derivatives, prentice - hall, inc. (1973).
274 Double a,b,c,d,e,eps,xm,p,q,r,tol1,tol2,u,v,w
278 /* eps is approximately the square root of the relative machine
284 - if (tol1 > 1e0) go to 10
286 R Version <= 1.3.x had
287 eps = .000244 ( = sqrt(5.954 e-8) )
288 -- now eps is passed as argument
297 v = a + c_Gold * (b - a);
302 *lspar = ratio * pow(16.0, (*spar * 6.0 - 2.0));
303 sslvrg_(penalt, dofoff, xs, ys, ws, ssw, n,
305 coef, sz, lev, crit, icrit, lspar, xwy,
307 sg0, sg1, sg2, sg3, abd,
308 p1ip, p2ip, ld4, ldnk, ier);
315 while(*ier == 0) { /* L20: */
317 if (m->control_pressed) { return 0; }
320 tol1 = *eps * fabs(x) + *tol / 3.;
325 /* Check the (somewhat peculiar) stopping criterion: note that
326 the RHS is negative as long as the interval [a,b] is not small:*/
327 if (fabs(x - xm) <= tol2 - (b - a) * .5 || *iter > maxit)
331 /* is golden-section necessary */
333 if (fabs(e) <= tol1 ||
334 /* if had Inf then go to golden-section */
335 fx >= BIG_f || fv >= BIG_f || fw >= BIG_f) goto L_GoldenSect;
339 r = (x - w) * (fx - fv);
340 q = (x - v) * (fx - fw);
341 p = (x - v) * q - (x - w) * r;
349 /* is parabola acceptable? Otherwise do golden-section */
351 if (fabs(p) >= fabs(.5 * q * r) ||
353 /* above line added by BDR;
354 * [the abs(.) >= abs() = 0 should have branched..]
355 * in FTN: COMMON above ensures q is NOT a register variable */
359 if (p <= q * (a - x) ||
360 p >= q * (b - x)) goto L_GoldenSect;
364 /* Parabolic Interpolation step */
368 /* f must not be evaluated too close to ax or bx */
369 if ((u - a < tol2 || b - u < tol2)) {
370 d = abs(tol1) * sgn(xm - x);
376 L_GoldenSect: /* a golden-section step */
378 if (x >= xm) e = a - x;
379 else/* x < xm*/ e = b - x;
384 u = x + ((fabs(d) >= tol1) ? d : (abs(tol1)*sgn(d)));
385 /* tol1 check : f must not be evaluated too close to x */
388 *lspar = ratio * pow(16.0, (*spar * 6.0 - 2.0));
389 sslvrg_(penalt, dofoff, xs, ys, ws, ssw, n,
391 coef, sz, lev, crit, icrit, lspar, xwy,
393 sg0, sg1, sg2, sg3, abd,
394 p1ip, p2ip, ld4, ldnk, ier);
401 /* update a, b, v, w, and x */
404 if (u >= x) a = x; else b = x;
411 if (u < x) a = u; else b = u;
413 if (fu <= fw || w == x) { /* L70: */
416 } else if (fu <= fv || v == x || v == w) { /* L80: */
420 }/* end main loop -- goto L20; */
444 }catch(exception& e) {
445 m->errorOut(e, "Spline", "sbart");
450 /***********************************************************/