1
subroutine clocur(iopt,ipar,idim,m,u,mx,x,w,k,s,nest,n,t,nc,c,fp,
3
c given the ordered set of m points x(i) in the idim-dimensional space
4
c with x(1)=x(m), and given also a corresponding set of strictly in-
5
c creasing values u(i) and the set of positive numbers w(i),i=1,2,...,m
6
c subroutine clocur determines a smooth approximating closed spline
9
c x2 = s2(u) u(1) <= u <= u(m)
12
c with sj(u),j=1,2,...,idim periodic spline functions of degree k with
13
c common knots t(j),j=1,2,...,n.
14
c if ipar=1 the values u(i),i=1,2,...,m must be supplied by the user.
15
c if ipar=0 these values are chosen automatically by clocur as
17
c v(i) = v(i-1) + dist(x(i),x(i-1)) ,i=2,3,...,m
18
c u(i) = v(i)/v(m) ,i=1,2,...,m
19
c if iopt=-1 clocur calculates the weighted least-squares closed spline
20
c curve according to a given set of knots.
21
c if iopt>=0 the number of knots of the splines sj(u) and the position
22
c t(j),j=1,2,...,n is chosen automatically by the routine. the smooth-
23
c ness of s(u) is then achieved by minimalizing the discontinuity
24
c jumps of the k-th derivative of s(u) at the knots t(j),j=k+2,k+3,...,
25
c n-k-1. the amount of smoothness is determined by the condition that
26
c f(p)=sum((w(i)*dist(x(i),s(u(i))))**2) be <= s, with s a given non-
27
c negative constant, called the smoothing factor.
28
c the fit s(u) is given in the b-spline representation and can be
29
c evaluated by means of subroutine curev.
32
c call clocur(iopt,ipar,idim,m,u,mx,x,w,k,s,nest,n,t,nc,c,
33
c * fp,wrk,lwrk,iwrk,ier)
36
c iopt : integer flag. on entry iopt must specify whether a weighted
37
c least-squares closed spline curve (iopt=-1) or a smoothing
38
c closed spline curve (iopt=0 or 1) must be determined. if
39
c iopt=0 the routine will start with an initial set of knots
40
c t(i)=u(1)+(u(m)-u(1))*(i-k-1),i=1,2,...,2*k+2. if iopt=1 the
41
c routine will continue with the knots found at the last call.
42
c attention: a call with iopt=1 must always be immediately
43
c preceded by another call with iopt=1 or iopt=0.
45
c ipar : integer flag. on entry ipar must specify whether (ipar=1)
46
c the user will supply the parameter values u(i),or whether
47
c (ipar=0) these values are to be calculated by clocur.
49
c idim : integer. on entry idim must specify the dimension of the
50
c curve. 0 < idim < 11.
52
c m : integer. on entry m must specify the number of data points.
53
c m > 1. unchanged on exit.
54
c u : real array of dimension at least (m). in case ipar=1,before
55
c entry, u(i) must be set to the i-th value of the parameter
56
c variable u for i=1,2,...,m. these values must then be
57
c supplied in strictly ascending order and will be unchanged
58
c on exit. in case ipar=0, on exit,the array will contain the
59
c values u(i) as determined by clocur.
60
c mx : integer. on entry mx must specify the actual dimension of
61
c the array x as declared in the calling (sub)program. mx must
62
c not be too small (see x). unchanged on exit.
63
c x : real array of dimension at least idim*m.
64
c before entry, x(idim*(i-1)+j) must contain the j-th coord-
65
c inate of the i-th data point for i=1,2,...,m and j=1,2,...,
66
c idim. since first and last data point must coincide it
67
c means that x(j)=x(idim*(m-1)+j),j=1,2,...,idim.
69
c w : real array of dimension at least (m). before entry, w(i)
70
c must be set to the i-th value in the set of weights. the
71
c w(i) must be strictly positive. w(m) is not used.
72
c unchanged on exit. see also further comments.
73
c k : integer. on entry k must specify the degree of the splines.
74
c 1<=k<=5. it is recommended to use cubic splines (k=3).
75
c the user is strongly dissuaded from choosing k even,together
76
c with a small s-value. unchanged on exit.
77
c s : real.on entry (in case iopt>=0) s must specify the smoothing
78
c factor. s >=0. unchanged on exit.
79
c for advice on the choice of s see further comments.
80
c nest : integer. on entry nest must contain an over-estimate of the
81
c total number of knots of the splines returned, to indicate
82
c the storage space available to the routine. nest >=2*k+2.
83
c in most practical situation nest=m/2 will be sufficient.
84
c always large enough is nest=m+2*k, the number of knots
85
c needed for interpolation (s=0). unchanged on exit.
87
c unless ier = 10 (in case iopt >=0), n will contain the
88
c total number of knots of the smoothing spline curve returned
89
c if the computation mode iopt=1 is used this value of n
90
c should be left unchanged between subsequent calls.
91
c in case iopt=-1, the value of n must be specified on entry.
92
c t : real array of dimension at least (nest).
93
c on succesful exit, this array will contain the knots of the
94
c spline curve,i.e. the position of the interior knots t(k+2),
95
c t(k+3),..,t(n-k-1) as well as the position of the additional
96
c t(1),t(2),..,t(k+1)=u(1) and u(m)=t(n-k),...,t(n) needed for
97
c the b-spline representation.
98
c if the computation mode iopt=1 is used, the values of t(1),
99
c t(2),...,t(n) should be left unchanged between subsequent
100
c calls. if the computation mode iopt=-1 is used, the values
101
c t(k+2),...,t(n-k-1) must be supplied by the user, before
102
c entry. see also the restrictions (ier=10).
103
c nc : integer. on entry nc must specify the actual dimension of
104
c the array c as declared in the calling (sub)program. nc
105
c must not be too small (see c). unchanged on exit.
106
c c : real array of dimension at least (nest*idim).
107
c on succesful exit, this array will contain the coefficients
108
c in the b-spline representation of the spline curve s(u),i.e.
109
c the b-spline coefficients of the spline sj(u) will be given
110
c in c(n*(j-1)+i),i=1,2,...,n-k-1 for j=1,2,...,idim.
111
c fp : real. unless ier = 10, fp contains the weighted sum of
112
c squared residuals of the spline curve returned.
113
c wrk : real array of dimension at least m*(k+1)+nest*(7+idim+5*k).
114
c used as working space. if the computation mode iopt=1 is
115
c used, the values wrk(1),...,wrk(n) should be left unchanged
116
c between subsequent calls.
117
c lwrk : integer. on entry,lwrk must specify the actual dimension of
118
c the array wrk as declared in the calling (sub)program. lwrk
119
c must not be too small (see wrk). unchanged on exit.
120
c iwrk : integer array of dimension at least (nest).
121
c used as working space. if the computation mode iopt=1 is
122
c used,the values iwrk(1),...,iwrk(n) should be left unchanged
123
c between subsequent calls.
124
c ier : integer. unless the routine detects an error, ier contains a
125
c non-positive value on exit, i.e.
126
c ier=0 : normal return. the close curve returned has a residual
127
c sum of squares fp such that abs(fp-s)/s <= tol with tol a
128
c relative tolerance set to 0.001 by the program.
129
c ier=-1 : normal return. the curve returned is an interpolating
130
c spline curve (fp=0).
131
c ier=-2 : normal return. the curve returned is the weighted least-
132
c squares point,i.e. each spline sj(u) is a constant. in
133
c this extreme case fp gives the upper bound fp0 for the
134
c smoothing factor s.
135
c ier=1 : error. the required storage space exceeds the available
136
c storage space, as specified by the parameter nest.
137
c probably causes : nest too small. if nest is already
138
c large (say nest > m/2), it may also indicate that s is
140
c the approximation returned is the least-squares closed
141
c curve according to the knots t(1),t(2),...,t(n). (n=nest)
142
c the parameter fp gives the corresponding weighted sum of
143
c squared residuals (fp>s).
144
c ier=2 : error. a theoretically impossible result was found during
145
c the iteration proces for finding a smoothing curve with
146
c fp = s. probably causes : s too small.
147
c there is an approximation returned but the corresponding
148
c weighted sum of squared residuals does not satisfy the
149
c condition abs(fp-s)/s < tol.
150
c ier=3 : error. the maximal number of iterations maxit (set to 20
151
c by the program) allowed for finding a smoothing curve
152
c with fp=s has been reached. probably causes : s too small
153
c there is an approximation returned but the corresponding
154
c weighted sum of squared residuals does not satisfy the
155
c condition abs(fp-s)/s < tol.
156
c ier=10 : error. on entry, the input data are controlled on validity
157
c the following restrictions must be satisfied.
158
c -1<=iopt<=1, 1<=k<=5, m>1, nest>2*k+2, w(i)>0,i=1,2,...,m
159
c 0<=ipar<=1, 0<idim<=10, lwrk>=(k+1)*m+nest*(7+idim+5*k),
160
c nc>=nest*idim, x(j)=x(idim*(m-1)+j), j=1,2,...,idim
161
c if ipar=0: sum j=1,idim (x(i*idim+j)-x((i-1)*idim+j))**2>0
163
c if ipar=1: u(1)<u(2)<...<u(m)
164
c if iopt=-1: 2*k+2<=n<=min(nest,m+2*k)
165
c u(1)<t(k+2)<t(k+3)<...<t(n-k-1)<u(m)
166
c (u(1)=0 and u(m)=1 in case ipar=0)
167
c the schoenberg-whitney conditions, i.e. there
168
c must be a subset of data points uu(j) with
169
c uu(j) = u(i) or u(i)+(u(m)-u(1)) such that
170
c t(j) < uu(j) < t(j+k+1), j=k+1,...,n-k-1
172
c if s=0 : nest >= m+2*k
173
c if one of these conditions is found to be violated,control
174
c is immediately repassed to the calling program. in that
175
c case there is no approximation returned.
178
c by means of the parameter s, the user can control the tradeoff
179
c between closeness of fit and smoothness of fit of the approximation.
180
c if s is too large, the curve will be too smooth and signal will be
181
c lost ; if s is too small the curve will pick up too much noise. in
182
c the extreme cases the program will return an interpolating curve if
183
c s=0 and the weighted least-squares point if s is very large.
184
c between these extremes, a properly chosen s will result in a good
185
c compromise between closeness of fit and smoothness of fit.
186
c to decide whether an approximation, corresponding to a certain s is
187
c satisfactory the user is highly recommended to inspect the fits
189
c recommended values for s depend on the weights w(i). if these are
190
c taken as 1/d(i) with d(i) an estimate of the standard deviation of
191
c x(i), a good s-value should be found in the range (m-sqrt(2*m),m+
192
c sqrt(2*m)). if nothing is known about the statistical error in x(i)
193
c each w(i) can be set equal to one and s determined by trial and
194
c error, taking account of the comments above. the best is then to
195
c start with a very large value of s ( to determine the weighted
196
c least-squares point and the upper bound fp0 for s) and then to
197
c progressively decrease the value of s ( say by a factor 10 in the
198
c beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the
199
c approximating curve shows more detail) to obtain closer fits.
200
c to economize the search for a good s-value the program provides with
201
c different modes of computation. at the first call of the routine, or
202
c whenever he wants to restart with the initial set of knots the user
204
c if iopt=1 the program will continue with the set of knots found at
205
c the last call of the routine. this will save a lot of computation
206
c time if clocur is called repeatedly for different values of s.
207
c the number of knots of the spline returned and their location will
208
c depend on the value of s and on the complexity of the shape of the
209
c curve underlying the data. but, if the computation mode iopt=1 is
210
c used, the knots returned may also depend on the s-values at previous
211
c calls (if these were smaller). therefore, if after a number of
212
c trials with different s-values and iopt=1, the user can finally
213
c accept a fit as satisfactory, it may be worthwhile for him to call
214
c clocur once more with the selected value for s but now with iopt=0.
215
c indeed, clocur may then return an approximation of the same quality
216
c of fit but with fewer knots and therefore better if data reduction
217
c is also an important objective for the user.
219
c the form of the approximating curve can strongly be affected by
220
c the choice of the parameter values u(i). if there is no physical
221
c reason for choosing a particular parameter u, often good results
222
c will be obtained with the choice of clocur(in case ipar=0), i.e.
223
c v(1)=0, v(i)=v(i-1)+q(i), i=2,...,m, u(i)=v(i)/v(m), i=1,..,m
225
c q(i)= sqrt(sum j=1,idim (xj(i)-xj(i-1))**2 )
226
c other possibilities for q(i) are
227
c q(i)= sum j=1,idim (xj(i)-xj(i-1))**2
228
c q(i)= sum j=1,idim abs(xj(i)-xj(i-1))
229
c q(i)= max j=1,idim abs(xj(i)-xj(i-1))
233
c other subroutines required:
234
c fpbacp,fpbspl,fpchep,fpclos,fpdisc,fpgivs,fpknot,fprati,fprota
237
c dierckx p. : algorithms for smoothing data with periodic and
238
c parametric splines, computer graphics and image
239
c processing 20 (1982) 171-184.
240
c dierckx p. : algorithms for smoothing data with periodic and param-
241
c etric splines, report tw55, dept. computer science,
243
c dierckx p. : curve and surface fitting with splines, monographs on
244
c numerical analysis, oxford university press, 1993.
248
c dept. computer science, k.u. leuven
249
c celestijnenlaan 200a, b-3001 heverlee, belgium.
250
c e-mail : Paul.Dierckx@cs.kuleuven.ac.be
252
c creation date : may 1979
253
c latest update : march 1987
256
c ..scalar arguments..
258
integer iopt,ipar,idim,m,mx,k,nest,n,nc,lwrk,ier
259
c ..array arguments..
260
real*8 u(m),x(mx),w(m),t(nest),c(nc),wrk(lwrk)
264
integer i,ia1,ia2,ib,ifp,ig1,ig2,iq,iz,i1,i2,j1,j2,k1,k2,lwest,
265
* maxit,m1,nmin,ncc,j
266
c ..function references..
268
c we set up the parameters tol and maxit
271
c before starting computations a data check is made. if the input data
272
c are invalid, control is immediately repassed to the calling program.
274
if(iopt.lt.(-1) .or. iopt.gt.1) go to 90
275
if(ipar.lt.0 .or. ipar.gt.1) go to 90
276
if(idim.le.0 .or. idim.gt.10) go to 90
277
if(k.le.0 .or. k.gt.5) go to 90
281
if(m.lt.2 .or. nest.lt.nmin) go to 90
283
if(mx.lt.m*idim .or. nc.lt.ncc) go to 90
284
lwest = m*k1+nest*(7+idim+5*k)
285
if(lwrk.lt.lwest) go to 90
289
if(x(i1).ne.x(i2)) go to 90
293
if(ipar.ne.0 .or. iopt.gt.0) go to 40
302
dist = dist+(x(i2)-x(i1))**2
304
u(i) = u(i-1)+sqrt(dist)
306
if(u(m).le.0.) go to 90
311
40 if(w(1).le.0.) go to 90
314
if(u(i).ge.u(i+1) .or. w(i).le.0.) go to 90
316
if(iopt.ge.0) go to 70
317
if(n.le.nmin .or. n.gt.nest) go to 90
333
call fpchep(u,m,t,n,k,ier)
334
if (ier.eq.0) go to 80
336
70 if(s.lt.0.) go to 90
337
if(s.eq.0. .and. nest.lt.(m+2*k)) go to 90
339
c we partition the working space and determine the spline approximation.
348
call fpclos(iopt,idim,m,u,mx,x,w,k,s,nest,tol,maxit,k1,k2,n,t,
349
* ncc,c,fp,wrk(ifp),wrk(iz),wrk(ia1),wrk(ia2),wrk(ib),wrk(ig1),
350
* wrk(ig2),wrk(iq),iwrk,ier)