fitpack-curfit

subroutine curfit(iopt,m,x,y,w,xb,xe,k,s,nest,n,t,c,fp, wrk,lwrk,iwrk,ier)
c     iopt  :整数;不变
c           iopt=-1 通过给定的knots集和,计算加权最小二乘样条
c           iopt=0  光滑样条,初始化点集t(i)=xb, t(i+k+1)=xe, i=1,2,...k+1
c           iopt=1 样条曲线s(x)的knots个数和t(j),j=1,2,...,n的位置自动计算;
c                  通过最小化s(x)的k阶导数在结点t(j),j=k+2, k+3,…,n-k-1处的
c                  不连续跳变来实现s(x)的平滑性。平滑度的大小取决于条件
c                  f(p)=sum((w(i)*(y(i)-s(x(i))))**2) be <= s, s给定的非负
c                  常数,称为平滑因子。拟合s(x)用b样条表示(b样条系数-
c                  c(j),j=1,2,...,n-k-1)可通过splev均值评估
c     m     :整数;不变
c           点个数;
c     x、y  :浮点数;不变
c           (x(i),y(i)), i=1,2,...,m; 点集;其中x(i)必须升序
c     w     :浮点数;不变
c           w(i),i=1,2,...,m; 正权重;
c     xb、xe:浮点数;不变
c           xb <= x <= xe点取值区间
c     k     :整数;不变;
c           1<=k<=5推荐;cubic splines (k=3);k为奇数
c     s     :浮点;不变
c           正数;
c     nest  :整数;
c           nest >=2*k+2
c           nest=m/2一般足够了
c           如果s=0,则nest=m/2
c     n     :整数
c           iopt >=0;ier !=10,n将包含返回的样条近似的总节数。
c           iopt=1;不变。
c           iopt=-1,n的值必须在输入时指定。
c     t     :数组;
c           样条结点,即。内部结点的位置t(k+2),t(k+3)...,t(n-k-1);
c           以及附加结点的位置t(1)=t(2)=…=t(k+1)=xb
c           和t(n-k)=…=t(n)=xe需要b样条表示。
c           iopt=1,则t(1),c t(2),…,t(n)不变。
c           iopt=-1,则值t(k+2),…,t(n-k-1)必须在输入之前由用户提供。
c     c     :数组;
c           c(1),c(2),..,c(n-k-1)样条系数
c     fp    :浮点
c           样条近似的平方残差的加权和
c     wrk   :浮点数组
c           iopt=1,wrk(1),…,wrk(n)不变。
c     lwrk  :整数;不变
c           lwrk必须数组wrk的维度。lwrk不能太小;
c     iwrk  :整数;
c           iopt=1,iwrk(1),…,iwrk(n)不变。
c     ier   :整数;
c           ier=0       :正常;abs(fp-s)/s <= tol;tol=0.001;fp残差平和
c           ier=-1      :正常;fp=0插值样条
c           ier=-2      :正常;k次的加权最小二乘多项式;平滑因子s的上界f0
c           ier=1       :错误;存储空间超过可用的存储空间,nest太小。
c                       如果nest已经很大(比如nest b> m/2),它也可能表明s太小了。
c                       结点t(1),t(2),…,t(n)(n=nest)加权最小二乘样条。参数fp
c                       给出相应的c平方残差(fp>s)的加权和。
c           ier=2       :错误;s太小。残差平方和不满足条件abs(fp-s)/s < tol
c           ier=3       :错误。fp=s的平滑样条;:s太小残差平方和不满足条件abs(fp-s)/s < tol。
c           ier=10      :错误。 -1<=iopt<=1, 1<=k<=5, m>k, nest>2*k+2, w(i)>0,i=1,2,...,m
c                       xb<=x(1)<x(2)<...<x(m)<=xe, lwrk>=(k+1)*m+nest*(7+3*k)
c                       if iopt=-1: 2*k+2<=n<=min(nest,m+k+1) xb<t(k+2)<t(k+3)<...<t(n-k-1)<xe
c                       t(j) < xx(j) < t(j+k+1), j=1,2,...,n-k-1
c                       iopt>=0: s>=0 if s=0 : nest >= m+k+1
c
c  further comments:
c     通过参数s,用户可以控制近似拟合的紧密性和拟合的平滑性之间的权衡。
c     如果s太大,样条会太光滑,信号会丢失;如果s太小,样条将接收太多的噪声。
c     在极端情况下,如果s=0,程序将返回一个插值样条,如果s非常大,则k次的
c     加权最小二乘多项式。在这两个极端之间,适当选择的s将导致c在拟合的紧密
c     性和拟合的平滑性之间的良好折衷。为了确定的近似,对应于某一s是否满足
c     的要求,强烈建议用户以图形的方式检查是否符合。
c     s的推荐值取决于权重w(i)。如果将这些取为1/d(i), d(i)是y(i)的标准差估计,
c     则应该在范围(m-sqrt(2*m),m+c sqrt(2*m))中找到一个良好的s值。
c     如果对y(i)c中的统计误差一无所知,则考虑到上面的注释,每个w(i)可以设置
c     为等于1和s,由试验和c误差确定。最好的方法是从一个非常大的s值开始(以确
c     定s的最小二乘多项式和相应的上限fp0),然后逐步减小s的值(例如在开始时减
c     少10倍,即s=fp0/10, fp0/100,…当逼近显示出更多的细节时,为了获得更接近
c     的拟合,为了节省寻找好的s值的时间,程序提供了不同的计算模式。在第一次调
c     用例程时,或者每当用户想用初始的节点集重新启动时,用户必须设置iopt=0。
c     如果iopt=1,程序将继续使用在例程最后调用时找到的结集。这将节省大量的计
c     算时间,如果对不同的s值重复调用曲线,返回的样条结的数量和它们的位置将
c     取决于s的值和数据底层函数形状的复杂性。但是,如果使用计算模式iopt=1,
c     则返回的节也可能取决于先前调用的s值(如果这些值较小)。因此,如果经过
c     不同s值和iopt=1的多次试验后,用户最终可以接受一个满意的拟合,那么他可
c     能值得再次调用curfit,使用s的选定值,但现在iopt=0.确实,curfit可能会
c     返回近似相同质量的拟合,但结更少,因此更好,如果数据缩减也是用户的一个重要目标。
c
c  other subroutines required:
c    fpback,fpbspl,fpchec,fpcurf,fpdisc,fpgivs,fpknot,fprati,fprota
c
c  references:
c   dierckx p. : an algorithm for smoothing, differentiation and integ-
c                ration of experimental data using spline functions,
c                j.comp.appl.maths 1 (1975) 165-184.
c   dierckx p. : a fast algorithm for smoothing data on a rectangular
c                grid while using spline functions, siam j.numer.anal.
c                19 (1982) 1286-1304.
c   dierckx p. : an improved algorithm for curve fitting with spline
c                functions, report tw54, dept. computer science,k.u.
c                leuven, 1981.
c   dierckx p. : curve and surface fitting with splines, monographs on
c                numerical analysis, oxford university press, 1993.
c
c  author:
c    p.dierckx
c    dept. computer science, k.u. leuven
c    celestijnenlaan 200a, b-3001 heverlee, belgium.
c    e-mail : Paul.Dierckx@cs.kuleuven.ac.be
c
c  creation date : may 1979
c  latest update : march 1987
c
c  ..
c  ..scalar arguments..
      real*8 xb,xe,s,fp
      integer iopt,m,k,nest,n,lwrk,ier
c  ..array arguments..
      real*8 x(m),y(m),w(m),t(nest),c(nest),wrk(lwrk)
      integer iwrk(nest)
c  ..local scalars..
      real*8 tol
      integer i,ia,ib,ifp,ig,iq,iz,j,k1,k2,lwest,maxit,nmin
c  ..
c  we set up the parameters tol and maxit
      maxit = 20
      tol = 0.1d-02
c  before starting computations a data check is made. if the input data
c  are invalid, control is immediately repassed to the calling program.
      ier = 10
      if(k.le.0 .or. k.gt.5) go to 50
      k1 = k+1
      k2 = k1+1
      if(iopt.lt.(-1) .or. iopt.gt.1) go to 50
      nmin = 2*k1
      if(m.lt.k1 .or. nest.lt.nmin) go to 50
      lwest = m*k1+nest*(7+3*k)
      if(lwrk.lt.lwest) go to 50
      if(xb.gt.x(1) .or. xe.lt.x(m)) go to 50
      do 10 i=2,m
         if(x(i-1).gt.x(i)) go to 50
  10  continue
      if(iopt.ge.0) go to 30
      if(n.lt.nmin .or. n.gt.nest) go to 50
      j = n
      do 20 i=1,k1
         t(i) = xb
         t(j) = xe
         j = j-1
  20  continue
      call fpchec(x,m,t,n,k,ier)
      if (ier.eq.0) go to 40
      go to 50
  30  if(s.lt.0.) go to 50
      if(s.eq.0. .and. nest.lt.(m+k1)) go to 50
c we partition the working space and determine the spline approximation.
  40  ifp = 1
      iz = ifp+nest
      ia = iz+nest
      ib = ia+nest*k1
      ig = ib+nest*k2
      iq = ig+nest*k2
      call fpcurf(iopt,x,y,w,m,xb,xe,k,s,nest,tol,maxit,k1,k2,n,t,c,fp,
     * wrk(ifp),wrk(iz),wrk(ia),wrk(ib),wrk(ig),wrk(iq),iwrk,ier)
  50  return
      end
   void FitPack::curfit(int iopt, int m, const double* x, const double* y,
       const double* w, double xb, double xe, int k, double s,
       int nest, int* n, double* t, double* c, double* fp,
       double* wrk, int lwrk, int* iwrk, int* ier)
   {
       
        /*  C++ translation by Werner Stille. */
       int i, ia, ib, ifp, ig, iq, iz, j, k1, k2, lwest, maxit, nmin;
       double tol;
       double** a, ** b, ** g, ** q;
       /*  we set up the parameters tol and maxit */
       maxit = 20;
       tol = 0.001;
       /*  before starting computations a data check is made. if the input data
        are invalid, control is immediately repassed to the calling program. */
       *ier = 10;
       if (k <= 0 || k > 5)
           return;
       k1 = k + 1;
       k2 = k1 + 1;
       if (iopt < -1 || iopt > 1)
           return;
       nmin = k1 << 1;
       if (m < k1 || nest < nmin)
           return;
       lwest = m * k1 + nest * (k * 3 + 7);
       if (lwrk < lwest)
           return;
       if (xb > x[0] || xe < x[m - 1] || w[0] <= 0)
           return;
       for (i = 1; i < m; i++)
           if (x[i - 1] >= x[i] || w[i] <= 0)
               return;
       if (iopt >= 0) {
           if (s < 0)
               return;
           if (s == 0 && nest < m + k1)
               return;
           *ier = 0;
       }
       else {
           if (*n < nmin || *n > nest)
               return;
           j = *n;
           for (i = 0; i < k1; i++) {
               t[i] = xb;
               t[--j] = xe;
           }
           fpchec(x, m, t, *n, k, ier);
           if (*ier)
               return;
       }
       /* we partition the working space and determine the spline approximation. */
       ifp = 0;
       iz = ifp + nest;
       ia = iz + nest;
       ib = ia + nest * k1;
       ig = ib + nest * k2;
       iq = ig + nest * k2;
       a = new double* [nest];
       b = new double* [nest];
       g = new double* [nest];
       q = new double* [nest];
       for (i = 0; i < nest; i++) {
           a[i] = &wrk[ia + i * k1];
           b[i] = &wrk[ib + i * k2];
           g[i] = &wrk[ig + i * k2];
       }
       for (i = 0; i < m; i++)
           q[i] = &wrk[iq + i * k1];
       fpcurf(iopt, x, y, w, m, xb, xe, k, s, nest, tol, maxit, k1, k2, n, t, c,
           fp, &wrk[ifp], &wrk[iz], a, b, g, q, iwrk, ier);
       delete[] q;
       delete[] g;
       delete[] b;
       delete[] a;
       return;
   }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值