00001 00002 c 00003 c Copyright (c) 1986,1987,1988,1989,1990,1991,1992,1993, 00004 c by Steve McMillan, Drexel University, Philadelphia, PA. 00005 c 00006 c All rights reserved. 00007 c 00008 c Redistribution and use in source and binary forms are permitted 00009 c provided that the above copyright notice and this paragraph are 00010 c duplicated in all such forms and that any documentation, 00011 c advertising materials, and other materials related to such 00012 c distribution and use acknowledge that the software was developed 00013 c by the author named above. 00014 c 00015 c THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00016 c IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00017 c WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00018 c 00019 00020 subroutine genfit(input,istart,nin,x,y,z,n,nz,iprompt,*) 00021 save 00022 c 00023 c Perform a general least-squares fit to y(x). 00024 c 00025 character*(*) input 00026 c 00027 parameter (MMAX = 21) 00028 dimension x(1),y(1),z(1),a(MMAX) 00029 c 00030 external poly,trig 00031 c 00032 c Equal weights for all points if nz <= 0. 00033 c Otherwise, specify the weights in the z array... 00034 c 00035 nw = nz 00036 if (nz.le.0) nw = 1 00037 c 00038 c Determine the array ranges. Note that the arrays MUST be sorted 00039 c in x for this to work. 00040 c 00041 call sort3(n,x,y,z) 00042 c 00043 10 if (istart.gt.nin) then 00044 i1 = 1 00045 nn = n 00046 ma = 2 00047 else 00048 ma = 1 00049 x1 = -1.e20 00050 x2 = 1.e20 00051 call readrq(input(istart:nin),3, 00052 & xma,x1,x2,dum,*1001) 00053 ma = nint(xma) 00054 if (ma.le.0) ma = 1 00055 c 00056 ma = ma + 1 00057 if (ma.gt.MMAX) then 00058 if (iprompt.eq.1) then 00059 call devoff 00060 write(6,*)' Must specify order <= ',MMAX-1 00061 go to 1001 00062 end if 00063 end if 00064 c 00065 i1=0 00066 do 150 i=1,n 00067 if (x(i).gt.x1.and.i1.eq.0) i1=i 00068 if (x(i).gt.x2) go to 160 00069 150 continue 00070 i = n+1 00071 160 i1 = max(1,i1) 00072 nn = i-i1 00073 if (nn.le.1) then 00074 write(6,*)'No points in specified range.' 00075 go to 1001 00076 end if 00077 end if 00078 c 00079 c Note: Input ma is the order of the polynomial fit (<=20). 00080 c Internal ma is one greater than this number. 00081 c 00082 c Rescale the x and y data to lie in [-1,1], to reduce the effects of 00083 c finite-precision arithmetic. This appears to do a better job than 00084 c scaling to [0,1]. 00085 c 00086 call minmax(x,n,xmin,xmax) 00087 xscale = 2./(xmax - xmin) 00088 xref = .5*(xmin+xmax) 00089 c 00090 call minmax(y,n,ymin,ymax) 00091 yscale = 2./(ymax - ymin) 00092 yref = .5*(ymin+ymax) 00093 c 00094 do 200 i=1,n 00095 x(i) = (x(i) - xref)*xscale 00096 y(i) = (y(i) - yref)*yscale 00097 200 continue 00098 c 00099 xscale = 1./xscale 00100 yscale = 1./yscale 00101 c 00102 x1 = x(i1) 00103 x2 = x(i1+nn-1) 00104 c 00105 c Use an intermediate C routine to allocate workspace space. 00106 c (Pointers are NOT standard FORTRAN yet!) 00107 c 00108 if (input(2:2).eq.'t') then 00109 call cfit(x(i1),y(i1),z(i1),nn,a,ma,trig,nw,chisq,iret) 00110 else 00111 call cfit(x(i1),y(i1),z(i1),nn,a,ma,poly,nw,chisq,iret) 00112 end if 00113 c 00114 c Print out some basic data on the fit obtained. 00115 c 00116 if (iprompt.eq.1) then 00117 call devoff 00118 write(6,250)(a(i),i=1,ma) 00119 250 format(' Coefficients: ',1p,5e11.3,:/(15x,5e11.3)) 00120 write(6,*)' Chisq = ',chisq 00121 end if 00122 c 00123 if (input(3:3).eq.'p') then 00124 c 00125 c Plot the fit. 00126 c 00127 call uplotin(x1*xscale+xref, 00128 & afunc(x1,a,ma,input(2:2))*yscale+yref,3) 00129 c 00130 do 300 i=1,n 00131 300 if (x(i).gt.x1.and.x(i).le.x2) 00132 & call uplotin(x(i)*xscale+xref, 00133 & afunc(x(i),a,ma,input(2:2))*yscale+yref,2) 00134 end if 00135 c 00136 c Unscale x and y before returning. 00137 c 00138 do 350 i=1,n 00139 x(i) = xscale*x(i) + xref 00140 y(i) = yscale*y(i) + yref 00141 350 continue 00142 c 00143 return 00144 1001 return 1 00145 c 00146 end 00147 00148 00149 function afunc(x,a,ma,which) 00150 save 00151 c 00152 parameter (MMAX = 21) 00153 dimension a(ma),f(MMAX) 00154 character*1 which 00155 c 00156 if (which.eq.'t') then 00157 call trig(x,f,ma) 00158 else 00159 call poly(x,f,ma) 00160 end if 00161 c 00162 sum = 0. 00163 do 10 i=1,ma 00164 10 sum = sum + a(i)*f(i) 00165 c 00166 afunc = sum 00167 c 00168 return 00169 end