子程序fppara(iopt,idim,m,u,mx,x,w,ub,ue,k,s,nest,tol,maxit,*k1、k2、n、t、nc、c、fp、fpint、z、a、b、g、q、nrdata、ier)c。。c。。标量参数。。真实ub、ue、s、tol、fp整数iopt,idim,m,mx,k,nest,maxit,k1,k2,n,nc,ierc。。数组参数。。实u(m)、x(mx)、w(m),t(嵌套)、c(nc)、fpint(嵌套),*z(nc),a(嵌套,k1),b(嵌套,k2),g(嵌套,kN2),q(m,k1整数nrdata(嵌套)c。。局部标量。。实际acc、con1、con4、con9、cos、fac、fpart、fpms、fpold、fp0、f1、f2、f3,*一半、一、p、pinv、piv、p1、p2、p3、rn、sin、store、term、ui、wi整数i,ich1,ich3,it,iter,i1,i2,i3,j,jj,j1,j2,k3,l,l0,*mk1,新,nk1,nmax,nmin,nplus,npl1,nrint,n8c。。本地阵列。。实h(7),xi(10)c。。函数引用真正的abs,fprati整数max0,min0c。。子程序引用。。c fpback、fpbspl、fpgivs、fpdisc、fpknot、fprotac。。c设置常数一个=0.1e+01con1=0.1e0con9=0.9e0con4=0.4e-01一半=0.5e0ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc第1部分:节数及其位置的测定cc******************************c给定一组节点,我们计算最小二乘曲线sinf(u)c和相应的残差平方和fp=f(p=inf)。c(c)c如果iopt=-1 sinf(u)是请求的曲线。c(c)如果iopt=0或iopt=1,我们检查是否可以接受结:c如果fp<=s,我们将继续使用当前的一组节点。c(c)如果fp>s,我们将增加节数并计算cc相应的最小二乘曲线,直到最终fp<=s.cc节的初始选择取决于s和iopt的值。c(c)c如果s=0,我们有样条插值;在这种情况下,c的数量c节等于nmax=m+k+1。c(c)如果s>0和c我们首先计算c的最小二乘多项式曲线c度k;n=nmin=2*k+2 cc iopt=1我们从最后c处发现的结集开始c调用例程,但s>fp0的情况除外;然后是c我们直接计算k次多项式曲线ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc确定nmin,即多项式近似的节点数。nmin=2*k1如果(iopt.lt.0)转到60c计算acc,f(p)的根的绝对公差=s。acc=公差*sc确定nmax,用于样条插值的节点数。nmax=m+k1如果(s.gt.0),则转到45c如果s=0,s(u)是插值曲线。c测试所需存储空间是否超过可用存储空间。n=nmax(最大值)如果(nmax.gt.nest)转到420c在插值的情况下找到内部节点的位置。10 mk1=m-k1如果(mk1.eq.0)转到60k3=k/2i=k2j=k3+2如果(k3*2.eq.k)转到30做20 l=1,mk1t(i)=u(j)i=i+1j=j+120继续转到6030做40 l=1,mk1t(i)=(u(j)+u(j-1))*一半i=i+1j=j+140继续转到60如果s>0,我们最初选择的结取决于iopt的值。如果iopt=0或iopt=1且s>=fp0,我们开始计算最小二乘c多项式曲线,它是一条没有内部节点的样条曲线。c如果iopt=1和fp0>s,我们开始计算最小二乘样条曲线c根据上次调用例程时发现的一组节点。45如果(iopt.eq.0)转到50如果(n.eq.nmin)转到50fp0=fpint(n)fpold=fpint(n-1)nplus=nrdata(n)如果(fp0.gt.s)转到6050 n=分钟fpold=0。nplus=0nrdata(1)=m-2c不同节组的主回路。m是保存上限c表示试验次数。60 do 200 iter=1,m如果(n.eq.nmin)ier=-2c求nrint,t求节间距数。nrint=n-nmin+1c找到所需的附加结的位置c s(u)的b样条表示。nk1=n-k1i=ndo 70 j=1,k1t(j)=ubt(i)=uei=i-170继续c计算最小二乘样条曲线的b样条系数c sinf(u)。观测矩阵a是逐行建立的通过givens变换将c简化为上三角形式。c同时计算fp=f(p=inf)。fp=0。c初始化b样条系数和观测矩阵a。做75 i=1,ncz(i)=0。75继续做80 i=1,nk1do 80 j=1,k1a(i,j)=0。80继续l=k1jj=0做130=1,mc获取当前数据点u(it),x(it)。ui=u(it)wi=w(it)do 83 j=1,idimjj=jj+1xi(j)=x(jj)*wi83继续c搜索结间隔t(l)<=ui<t(l+1)。85如果(ui.lt.t(l+1))或。l.eq.nk1)转到90l=l+1转到85c在ui中计算(k+1)非零b样条并将其存储在q中。90调用fpbspl(t,n,k,ui,l,h)do 95 i=1,k1q(it,i)=h(i)h(i)=h(i95继续c将观察矩阵的新行旋转为三角形。j=l-k1do 110 i=1,k1j=j+1piv=h(i)如果(piv.eq.0),请转至110c计算givens变换的参数。调用fpgivs(piv,a(j,1),cos,sin)c转换到右侧。j1=jdo 97 j2=1,idim调用fprota(cos,sin,xi(j2),z(j1))j1=j1+n97继续如果(即k1)转到120i2=1i3=i+1do 100 i1=i3,k1i2=i2+1c到左手边的转换。调用fprota(cos,sin,h(i1),a(j,i2))100继续110继续c将此行的贡献与残差平方和相加c右侧。120做125 j2=1,idimfp=fp+xi(j2)**2125续130继续如果(ier.eq.(-2))fp0=fpfpint(n)=fp0fpint(n-1)=fpoldnrdata(n)=净现值c后向替换以获得b样条系数。j1=1do 135 j2=1,idim调用fpback(a,z(j1),nk1,k1,c(j1,nest)j1=j1+n135续c检验近似sinf(u)是否是可接受的解。如果(iopt.lt.0)转到440fpms=fp-s如果(abs(fpms).lt.acc)转到440c如果f(p=inf)<s接受节的选择。如果(fpms.lt.)转到250c如果n=nmax,sinf(u)是插值样条曲线。如果(n.eq.nmax)转至430c增加节数。c如果n=嵌套,我们不能增加节数,因为c存储容量限制。如果(n.eq.nest)转至420c决定我们要添加的节点数nplus。如果(ier.eq.0)转到140nplus=1ier=0转到150140个npl1=nplus*2rn=净现值如果(fpold-fp.gt.acc)npl1=rn*fpms/(fpold-fp)nplus=最小0(nplus*2,最大0(npl1,nplus/2,1))150 fpold=fpc计算每个结间隔的平方残差之和c t(j+k)<=u(i)<=t(j+k+1)并将其存储在fpint(j)中,j=1,2,。。。编号:。fpart=0。i=1l=k2新=0jj=0做180=1,m如果(u(it).lt.t(l).或。l.gt.nk1)转到160新=1l=l+1160项=0。l0=l-k2do 175 j2=1,idimfac=0。j1=l0do 170 j=1,k1j1=j1+1fac=fac+c(j1)*q(it,j)170继续jj=jj+1术语=术语+(w(it)*(fac-x(jj)))**2l0=l0+n175继续fpart=fpart+术语如果(new.eq.0)转到180存储=术语*halffpint(i)=fpart-storei=i+1fpart=存储新=0180继续fpint(nrint)=fpartdo 190 l=1,净现值c加一个新结。调用fpknot(u,m,t,n,fpint,nrdata,nrint,nest,1)c如果n=nmax,我们将节点定位为插值如果(n.eq.nmax)转至10c测试我们是否不能进一步增加节数。如果(n.eq.nest)转到200190续c使用新的一组节点重新开始计算。200继续c检验最小二乘k次多项式曲线是否为我们近似问题的c解。250如果(ier.eq.(-2))转到440ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc第2部分:光滑样条曲线sp(u)的确定。c(c)c******************************c我们已经确定了节数及其位置。c(c)我们现在计算平滑曲线c的b样条系数c sp(u)。观测矩阵a被矩阵c的行所扩展c b表示sp(u)在c处的k阶导数不连续性c内部节点t(k+2),。。。t(n-k-1)必须为零。corres-cc这些附加行的积水重量设置为1/p。c然后我们必须迭代地确定p的值,这样f(p),c残差平方和等于s。我们已经知道最小cc平方k次多项式曲线对应于p=0,且cc最小二乘样条曲线对应于p=无穷大。c这里提出的c迭代过程利用了rational cc插值。因为f(p)是凸的且严格递减的cp的c函数,它可以近似为有理函数cc r(p)=(u*p+v)/(p+w)。p(p1,p2,p3)的三个值与对应的-c使用f(p)(f1=f(p1)-s,f2=f(p2)-s、f3=f(p3)-s)的cing值cc计算p的新值,使r(p)=s。收敛为cc通过取f1>0和f3<0来保证。c(c)ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc计算的k阶导数的不连续跳跃c节点t(l)处的b样条曲线,l=k+2,。。。n-k-1并存储在b中。调用fpdisc(t,n,k2,b,nest)c p的初始值。p1=0。f1=fp0-sp3=-1f3=帧/分钟p=0。做252 i=1,nk1p=p+a(i,1)252续rn=nk1p=转/转ich1=0ich3=0n8=n-分钟c迭代过程以找到f(p)=s的根。do 360 iter=1,最大值c将权重为1/p的矩阵b的行旋转到c存储在g中的三角形观测矩阵a。pinv=一个/pdo 255 i=1,ncc(i)=z(i)255续做260 i=1,nk1g(i,k2)=0。do 260 j=1,k1g(i,j)=a(i,j)260继续做300=1,n8c矩阵b的行通过givens变换旋转成三角形做270 i=1,k2h(i)=b(it,i)*pinv270继续do 275 j=1,idimxi(j)=0。275续做290 j=它,nk1piv=小时(1)c计算givens变换的参数。调用fpgivs(piv,g(j,1),cos,sin)c转换到右侧。j1=jdo 277 j2=1,idim调用fprota(cos,sin,xi(j2),c(j1))j1=j1+n277续如果(j.eq.nk1)转到300i2=k1如果(j.gt.n8)i2=nk1-j做280 i=1,i2c到左手边的转换。i1=i+1调用fprota(cos,sin,h(i1),g(j,i1))h(i)=h(i1)280继续h(i2+1)=0。290继续300继续c向后代换得到b样条系数。j1=1do 305 j2=1,idim调用fpback(g,c(j1),nk1,k2,c(j1),嵌套)j1=j1+n305继续c计算f(p)。fp=0。l=k2jj=0做330=1,m如果(u(it)ltt(l).或。l.gt.nk1)转到310l=l+1310 l0=l-k2术语=0。do 325 j2=1,idimfac=0。j1=l0do 320 j=1,k1j1=j1+1fac=fac+c(j1)*q(it,j)320继续jj=jj+1术语=术语+(fac-x(jj))**2l0=l0+n325续fp=fp+术语*w(it)**2330继续c检验近似值sp(u)是否是可接受的解。fpms=fp-s如果(abs(fpms).lt.acc)转到440c测试是否达到最大迭代次数。如果(iter.eq.maxit)转到400c执行迭代过程的另一个步骤。p2=pf2=英尺/分钟如果(ich3.ne.0)转到340如果((f2-f3).gt.acc)转至335c我们最初选择的p太大了。p3=p2f3=f2p=p*con4如果(p.le.p1)p=p1*con9+p2*con1转到360335如果(f2.lt.)ich3=1340如果(ich1.ne.0)转到350如果((f1-f2).gt.acc)转到345c我们最初选择的p太小p1=p2f1=f2p=p/con4如果(p3.lt.0.)转到360如果(p.ge.p3)p=p2*con1+p3*con9转到360如果(f2.gt.0.)ich1=1,则为345c测试迭代过程是否按照理论进行应为c。350如果(f2.ge.f1.或.f2.le.f3)转至410c找到p的新值。p=fprati(p1、f1、p2、f2、p3、f3)360继续c错误代码和消息。400 ier=3转到440410 ier=2转到440420 ier=1转到440430 ier=-1440返回结束