~ubuntu-branches/ubuntu/raring/python-scipy/raring-proposed

« back to all changes in this revision

Viewing changes to Lib/sandbox/spline/fitpack/fppara.f

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-01-07 14:12:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070107141212-mm0ebkh5b37hcpzn
* Remove build dependency on python-numpy-dev.
* python-scipy: Depend on python-numpy instead of python-numpy-dev.
* Package builds on other archs than i386. Closes: #402783.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
      subroutine fppara(iopt,idim,m,u,mx,x,w,ub,ue,k,s,nest,tol,maxit,
 
2
     * k1,k2,n,t,nc,c,fp,fpint,z,a,b,g,q,nrdata,ier)
 
3
c  ..
 
4
c  ..scalar arguments..
 
5
      real*8 ub,ue,s,tol,fp
 
6
      integer iopt,idim,m,mx,k,nest,maxit,k1,k2,n,nc,ier
 
7
c  ..array arguments..
 
8
      real*8 u(m),x(mx),w(m),t(nest),c(nc),fpint(nest),
 
9
     * z(nc),a(nest,k1),b(nest,k2),g(nest,k2),q(m,k1)
 
10
      integer nrdata(nest)
 
11
c  ..local scalars..
 
12
      real*8 acc,con1,con4,con9,cos,fac,fpart,fpms,fpold,fp0,f1,f2,f3,
 
13
     * half,one,p,pinv,piv,p1,p2,p3,rn,sin,store,term,ui,wi
 
14
      integer i,ich1,ich3,it,iter,i1,i2,i3,j,jj,j1,j2,k3,l,l0,
 
15
     * mk1,new,nk1,nmax,nmin,nplus,npl1,nrint,n8
 
16
c  ..local arrays..
 
17
      real*8 h(7),xi(10)
 
18
c  ..function references
 
19
      real*8 abs,fprati
 
20
      integer max0,min0
 
21
c  ..subroutine references..
 
22
c    fpback,fpbspl,fpgivs,fpdisc,fpknot,fprota
 
23
c  ..
 
24
c  set constants
 
25
      one = 0.1e+01
 
26
      con1 = 0.1e0
 
27
      con9 = 0.9e0
 
28
      con4 = 0.4e-01
 
29
      half = 0.5e0
 
30
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
 
31
c  part 1: determination of the number of knots and their position     c
 
32
c  **************************************************************      c
 
33
c  given a set of knots we compute the least-squares curve sinf(u),    c
 
34
c  and the corresponding sum of squared residuals fp=f(p=inf).         c
 
35
c  if iopt=-1 sinf(u) is the requested curve.                          c
 
36
c  if iopt=0 or iopt=1 we check whether we can accept the knots:       c
 
37
c    if fp <=s we will continue with the current set of knots.         c
 
38
c    if fp > s we will increase the number of knots and compute the    c
 
39
c       corresponding least-squares curve until finally fp<=s.         c
 
40
c    the initial choice of knots depends on the value of s and iopt.   c
 
41
c    if s=0 we have spline interpolation; in that case the number of   c
 
42
c    knots equals nmax = m+k+1.                                        c
 
43
c    if s > 0 and                                                      c
 
44
c      iopt=0 we first compute the least-squares polynomial curve of   c
 
45
c      degree k; n = nmin = 2*k+2                                      c
 
46
c      iopt=1 we start with the set of knots found at the last         c
 
47
c      call of the routine, except for the case that s > fp0; then     c
 
48
c      we compute directly the polynomial curve of degree k.           c
 
49
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
 
50
c  determine nmin, the number of knots for polynomial approximation.
 
51
      nmin = 2*k1
 
52
      if(iopt.lt.0) go to 60
 
53
c  calculation of acc, the absolute tolerance for the root of f(p)=s.
 
54
      acc = tol*s
 
55
c  determine nmax, the number of knots for spline interpolation.
 
56
      nmax = m+k1
 
57
      if(s.gt.0.) go to 45
 
58
c  if s=0, s(u) is an interpolating curve.
 
59
c  test whether the required storage space exceeds the available one.
 
60
      n = nmax
 
61
      if(nmax.gt.nest) go to 420
 
62
c  find the position of the interior knots in case of interpolation.
 
63
  10  mk1 = m-k1
 
64
      if(mk1.eq.0) go to 60
 
65
      k3 = k/2
 
66
      i = k2
 
67
      j = k3+2
 
68
      if(k3*2.eq.k) go to 30
 
69
      do 20 l=1,mk1
 
70
        t(i) = u(j)
 
71
        i = i+1
 
72
        j = j+1
 
73
  20  continue
 
74
      go to 60
 
75
  30  do 40 l=1,mk1
 
76
        t(i) = (u(j)+u(j-1))*half
 
77
        i = i+1
 
78
        j = j+1
 
79
  40  continue
 
80
      go to 60
 
81
c  if s>0 our initial choice of knots depends on the value of iopt.
 
82
c  if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares
 
83
c  polynomial curve which is a spline curve without interior knots.
 
84
c  if iopt=1 and fp0>s we start computing the least squares spline curve
 
85
c  according to the set of knots found at the last call of the routine.
 
86
  45  if(iopt.eq.0) go to 50
 
87
      if(n.eq.nmin) go to 50
 
88
      fp0 = fpint(n)
 
89
      fpold = fpint(n-1)
 
90
      nplus = nrdata(n)
 
91
      if(fp0.gt.s) go to 60
 
92
  50  n = nmin
 
93
      fpold = 0.
 
94
      nplus = 0
 
95
      nrdata(1) = m-2
 
96
c  main loop for the different sets of knots. m is a save upper bound
 
97
c  for the number of trials.
 
98
  60  do 200 iter = 1,m
 
99
        if(n.eq.nmin) ier = -2
 
100
c  find nrint, tne number of knot intervals.
 
101
        nrint = n-nmin+1
 
102
c  find the position of the additional knots which are needed for
 
103
c  the b-spline representation of s(u).
 
104
        nk1 = n-k1
 
105
        i = n
 
106
        do 70 j=1,k1
 
107
          t(j) = ub
 
108
          t(i) = ue
 
109
          i = i-1
 
110
  70    continue
 
111
c  compute the b-spline coefficients of the least-squares spline curve
 
112
c  sinf(u). the observation matrix a is built up row by row and
 
113
c  reduced to upper triangular form by givens transformations.
 
114
c  at the same time fp=f(p=inf) is computed.
 
115
        fp = 0.
 
116
c  initialize the b-spline coefficients and the observation matrix a.
 
117
        do 75 i=1,nc
 
118
          z(i) = 0.
 
119
  75    continue
 
120
        do 80 i=1,nk1
 
121
          do 80 j=1,k1
 
122
            a(i,j) = 0.
 
123
  80    continue
 
124
        l = k1
 
125
        jj = 0
 
126
        do 130 it=1,m
 
127
c  fetch the current data point u(it),x(it).
 
128
          ui = u(it)
 
129
          wi = w(it)
 
130
          do 83 j=1,idim
 
131
             jj = jj+1
 
132
             xi(j) = x(jj)*wi
 
133
  83      continue
 
134
c  search for knot interval t(l) <= ui < t(l+1).
 
135
  85      if(ui.lt.t(l+1) .or. l.eq.nk1) go to 90
 
136
          l = l+1
 
137
          go to 85
 
138
c  evaluate the (k+1) non-zero b-splines at ui and store them in q.
 
139
  90      call fpbspl(t,n,k,ui,l,h)
 
140
          do 95 i=1,k1
 
141
            q(it,i) = h(i)
 
142
            h(i) = h(i)*wi
 
143
  95      continue
 
144
c  rotate the new row of the observation matrix into triangle.
 
145
          j = l-k1
 
146
          do 110 i=1,k1
 
147
            j = j+1
 
148
            piv = h(i)
 
149
            if(piv.eq.0.) go to 110
 
150
c  calculate the parameters of the givens transformation.
 
151
            call fpgivs(piv,a(j,1),cos,sin)
 
152
c  transformations to right hand side.
 
153
            j1 = j
 
154
            do 97 j2 =1,idim
 
155
               call fprota(cos,sin,xi(j2),z(j1))
 
156
               j1 = j1+n
 
157
  97        continue
 
158
            if(i.eq.k1) go to 120
 
159
            i2 = 1
 
160
            i3 = i+1
 
161
            do 100 i1 = i3,k1
 
162
              i2 = i2+1
 
163
c  transformations to left hand side.
 
164
              call fprota(cos,sin,h(i1),a(j,i2))
 
165
 100        continue
 
166
 110      continue
 
167
c  add contribution of this row to the sum of squares of residual
 
168
c  right hand sides.
 
169
 120      do 125 j2=1,idim
 
170
             fp  = fp+xi(j2)**2
 
171
 125      continue
 
172
 130    continue
 
173
        if(ier.eq.(-2)) fp0 = fp
 
174
        fpint(n) = fp0
 
175
        fpint(n-1) = fpold
 
176
        nrdata(n) = nplus
 
177
c  backward substitution to obtain the b-spline coefficients.
 
178
        j1 = 1
 
179
        do 135 j2=1,idim
 
180
           call fpback(a,z(j1),nk1,k1,c(j1),nest)
 
181
           j1 = j1+n
 
182
 135    continue
 
183
c  test whether the approximation sinf(u) is an acceptable solution.
 
184
        if(iopt.lt.0) go to 440
 
185
        fpms = fp-s
 
186
        if(abs(fpms).lt.acc) go to 440
 
187
c  if f(p=inf) < s accept the choice of knots.
 
188
        if(fpms.lt.0.) go to 250
 
189
c  if n = nmax, sinf(u) is an interpolating spline curve.
 
190
        if(n.eq.nmax) go to 430
 
191
c  increase the number of knots.
 
192
c  if n=nest we cannot increase the number of knots because of
 
193
c  the storage capacity limitation.
 
194
        if(n.eq.nest) go to 420
 
195
c  determine the number of knots nplus we are going to add.
 
196
        if(ier.eq.0) go to 140
 
197
        nplus = 1
 
198
        ier = 0
 
199
        go to 150
 
200
 140    npl1 = nplus*2
 
201
        rn = nplus
 
202
        if(fpold-fp.gt.acc) npl1 = rn*fpms/(fpold-fp)
 
203
        nplus = min0(nplus*2,max0(npl1,nplus/2,1))
 
204
 150    fpold = fp
 
205
c  compute the sum of squared residuals for each knot interval
 
206
c  t(j+k) <= u(i) <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint.
 
207
        fpart = 0.
 
208
        i = 1
 
209
        l = k2
 
210
        new = 0
 
211
        jj = 0
 
212
        do 180 it=1,m
 
213
          if(u(it).lt.t(l) .or. l.gt.nk1) go to 160
 
214
          new = 1
 
215
          l = l+1
 
216
 160      term = 0.
 
217
          l0 = l-k2
 
218
          do 175 j2=1,idim
 
219
            fac = 0.
 
220
            j1 = l0
 
221
            do 170 j=1,k1
 
222
              j1 = j1+1
 
223
              fac = fac+c(j1)*q(it,j)
 
224
 170        continue
 
225
            jj = jj+1
 
226
            term = term+(w(it)*(fac-x(jj)))**2
 
227
            l0 = l0+n
 
228
 175      continue
 
229
          fpart = fpart+term
 
230
          if(new.eq.0) go to 180
 
231
          store = term*half
 
232
          fpint(i) = fpart-store
 
233
          i = i+1
 
234
          fpart = store
 
235
          new = 0
 
236
 180    continue
 
237
        fpint(nrint) = fpart
 
238
        do 190 l=1,nplus
 
239
c  add a new knot.
 
240
          call fpknot(u,m,t,n,fpint,nrdata,nrint,nest,1)
 
241
c  if n=nmax we locate the knots as for interpolation
 
242
          if(n.eq.nmax) go to 10
 
243
c  test whether we cannot further increase the number of knots.
 
244
          if(n.eq.nest) go to 200
 
245
 190    continue
 
246
c  restart the computations with the new set of knots.
 
247
 200  continue
 
248
c  test whether the least-squares kth degree polynomial curve is a
 
249
c  solution of our approximation problem.
 
250
 250  if(ier.eq.(-2)) go to 440
 
251
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
 
252
c  part 2: determination of the smoothing spline curve sp(u).          c
 
253
c  **********************************************************          c
 
254
c  we have determined the number of knots and their position.          c
 
255
c  we now compute the b-spline coefficients of the smoothing curve     c
 
256
c  sp(u). the observation matrix a is extended by the rows of matrix   c
 
257
c  b expressing that the kth derivative discontinuities of sp(u) at    c
 
258
c  the interior knots t(k+2),...t(n-k-1) must be zero. the corres-     c
 
259
c  ponding weights of these additional rows are set to 1/p.            c
 
260
c  iteratively we then have to determine the value of p such that f(p),c
 
261
c  the sum of squared residuals be = s. we already know that the least c
 
262
c  squares kth degree polynomial curve corresponds to p=0, and that    c
 
263
c  the least-squares spline curve corresponds to p=infinity. the       c
 
264
c  iteration process which is proposed here, makes use of rational     c
 
265
c  interpolation. since f(p) is a convex and strictly decreasing       c
 
266
c  function of p, it can be approximated by a rational function        c
 
267
c  r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond-  c
 
268
c  ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used      c
 
269
c  to calculate the new value of p such that r(p)=s. convergence is    c
 
270
c  guaranteed by taking f1>0 and f3<0.                                 c
 
271
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
 
272
c  evaluate the discontinuity jump of the kth derivative of the
 
273
c  b-splines at the knots t(l),l=k+2,...n-k-1 and store in b.
 
274
      call fpdisc(t,n,k2,b,nest)
 
275
c  initial value for p.
 
276
      p1 = 0.
 
277
      f1 = fp0-s
 
278
      p3 = -one
 
279
      f3 = fpms
 
280
      p = 0.
 
281
      do 252 i=1,nk1
 
282
         p = p+a(i,1)
 
283
 252  continue
 
284
      rn = nk1
 
285
      p = rn/p
 
286
      ich1 = 0
 
287
      ich3 = 0
 
288
      n8 = n-nmin
 
289
c  iteration process to find the root of f(p) = s.
 
290
      do 360 iter=1,maxit
 
291
c  the rows of matrix b with weight 1/p are rotated into the
 
292
c  triangularised observation matrix a which is stored in g.
 
293
        pinv = one/p
 
294
        do 255 i=1,nc
 
295
          c(i) = z(i)
 
296
 255    continue
 
297
        do 260 i=1,nk1
 
298
          g(i,k2) = 0.
 
299
          do 260 j=1,k1
 
300
            g(i,j) = a(i,j)
 
301
 260    continue
 
302
        do 300 it=1,n8
 
303
c  the row of matrix b is rotated into triangle by givens transformation
 
304
          do 270 i=1,k2
 
305
            h(i) = b(it,i)*pinv
 
306
 270      continue
 
307
          do 275 j=1,idim
 
308
            xi(j) = 0.
 
309
 275      continue
 
310
          do 290 j=it,nk1
 
311
            piv = h(1)
 
312
c  calculate the parameters of the givens transformation.
 
313
            call fpgivs(piv,g(j,1),cos,sin)
 
314
c  transformations to right hand side.
 
315
            j1 = j
 
316
            do 277 j2=1,idim
 
317
              call fprota(cos,sin,xi(j2),c(j1))
 
318
              j1 = j1+n
 
319
 277        continue
 
320
            if(j.eq.nk1) go to 300
 
321
            i2 = k1
 
322
            if(j.gt.n8) i2 = nk1-j
 
323
            do 280 i=1,i2
 
324
c  transformations to left hand side.
 
325
              i1 = i+1
 
326
              call fprota(cos,sin,h(i1),g(j,i1))
 
327
              h(i) = h(i1)
 
328
 280        continue
 
329
            h(i2+1) = 0.
 
330
 290      continue
 
331
 300    continue
 
332
c  backward substitution to obtain the b-spline coefficients.
 
333
        j1 = 1
 
334
        do 305 j2=1,idim
 
335
          call fpback(g,c(j1),nk1,k2,c(j1),nest)
 
336
          j1 =j1+n
 
337
 305    continue
 
338
c  computation of f(p).
 
339
        fp = 0.
 
340
        l = k2
 
341
        jj = 0
 
342
        do 330 it=1,m
 
343
          if(u(it).lt.t(l) .or. l.gt.nk1) go to 310
 
344
          l = l+1
 
345
 310      l0 = l-k2
 
346
          term = 0.
 
347
          do 325 j2=1,idim
 
348
            fac = 0.
 
349
            j1 = l0
 
350
            do 320 j=1,k1
 
351
              j1 = j1+1
 
352
              fac = fac+c(j1)*q(it,j)
 
353
 320        continue
 
354
            jj = jj+1
 
355
            term = term+(fac-x(jj))**2
 
356
            l0 = l0+n
 
357
 325      continue
 
358
          fp = fp+term*w(it)**2
 
359
 330    continue
 
360
c  test whether the approximation sp(u) is an acceptable solution.
 
361
        fpms = fp-s
 
362
        if(abs(fpms).lt.acc) go to 440
 
363
c  test whether the maximal number of iterations is reached.
 
364
        if(iter.eq.maxit) go to 400
 
365
c  carry out one more step of the iteration process.
 
366
        p2 = p
 
367
        f2 = fpms
 
368
        if(ich3.ne.0) go to 340
 
369
        if((f2-f3).gt.acc) go to 335
 
370
c  our initial choice of p is too large.
 
371
        p3 = p2
 
372
        f3 = f2
 
373
        p = p*con4
 
374
        if(p.le.p1) p=p1*con9 + p2*con1
 
375
        go to 360
 
376
 335    if(f2.lt.0.) ich3=1
 
377
 340    if(ich1.ne.0) go to 350
 
378
        if((f1-f2).gt.acc) go to 345
 
379
c  our initial choice of p is too small
 
380
        p1 = p2
 
381
        f1 = f2
 
382
        p = p/con4
 
383
        if(p3.lt.0.) go to 360
 
384
        if(p.ge.p3) p = p2*con1 + p3*con9
 
385
        go to 360
 
386
 345    if(f2.gt.0.) ich1=1
 
387
c  test whether the iteration process proceeds as theoretically
 
388
c  expected.
 
389
 350    if(f2.ge.f1 .or. f2.le.f3) go to 410
 
390
c  find the new value for p.
 
391
        p = fprati(p1,f1,p2,f2,p3,f3)
 
392
 360  continue
 
393
c  error codes and messages.
 
394
 400  ier = 3
 
395
      go to 440
 
396
 410  ier = 2
 
397
      go to 440
 
398
 420  ier = 1
 
399
      go to 440
 
400
 430  ier = -1
 
401
 440  return
 
402
      end