c subroutine regres.f c c source c Bevington, pages 172-175. c c purpose c make a mulitple linear regression fit to data with a specified c function which is linear in coefficients c c usage c call regres (x, y, sigmay, npts, nterms, m, mode, yfit, c a0, a, sigma0, sigmaa, r, rmul, chisqr, ftest) c c description of parameters c x - array of points for independent variable c y - array of points for dependent variable c sigmay - array of standard deviations for y data points c npts - number of pairs of data points c nterms - number of coefficients c m - array of inclusion/rejection criteria for fctn c mode - determines method of weighting least-squares fit c +1 (instrumental) weight(i) = 1./sigmay(i)**2 c 0 (no weighting) weight(i) = 1. c -1 (statistical) weight(i) = 1./y(i) c yfit - array of calculated values of y c a0 - constant term c a - array of coefficients c sigma0 - standard deviation of a0 c sigmaa - array of standard deviations for coefficients c r - array of linear correlation coefficients c rmul - multiple linear correlation coefficient c chisqr - reduced chi square for fit c ftest - value of f for test of fit c c subroutines and function subprograms required c fctn (x, i, j, m) c evaluates the function for the jth term and the ith data point c using the array m to specify terms in the function c matinv (array, nterms, det) c inverts a symmetric two-dimensional matrix of degree nterms c and calculates its determinant c c comments c (dim npts changed 100->1000 21-may-84 dct) c dimension statement valid for npts up to 100 and nterms up to 10 c sigmaag changed to sigmaa in statement following statement 132 c subroutine pfregs (x,y,sigmay,npts,nterms,m,mode,yfit, *a0,a,sigma0,sigmaa,r,rmul,chisqr,ftest,fctn) double precision array,sum,ymean,sigma,chisq,xmean,sigmax dimension x(1),y(1),sigmay(1),m(1),yfit(1),a(1),sigmaa(1), *r(1) dimension weight(1000),xmean(10),sigmax(10),array(10,10) external fctn c c initialize sums and arrays c 11 sum=0. ymean=0. sigma=0. chisq=0. rmul=0. do 17 i=1,npts 17 yfit(i)=0. 21 do 28 j=1,nterms xmean(j)=0. sigmax(j)=0. r(j)=0. a(j)=0. sigmaa(j)=0. do 28 k=1,nterms 28 array(j,k)=0. c c accumulate weighted sums c 30 do 50 i=1,npts 31 if (mode) 32,37,39 32 if (y(i)) 35,37,33 33 weight(i)=1./y(i) goto 41 35 weight(i)=1./(-y(i)) goto 41 37 weight(i)=1. goto 41 39 weight(i)=1./sigmay(i)**2 41 sum=sum+weight(i) ymean=ymean+weight(i)*y(i) do 44 j=1,nterms 44 xmean(j)=xmean(j)+weight(i)*fctn(x,i,j,m) 50 continue 51 ymean=ymean/sum do 53 j=1,nterms 53 xmean(j)=xmean(j)/sum fnpts=npts wmean=sum/fnpts do 57 i=1,npts 57 weight(i)=weight(i)/wmean c c accumulate matrices r and array c 61 do 67 i=1,npts sigma=sigma+weight(i)*(y(i)-ymean)**2 do 67 j=1,nterms sigmax(j)=sigmax(j)+weight(i)*(fctn(x,i,j,m)-xmean(j))**2 r(j)=r(j)+weight(i)*(fctn(x,i,j,m)-xmean(j))*(y(i)-ymean) do 67 k=1,j 67 array(j,k)=array(j,k)+weight(i)*(fctn(x,i,j,m)-xmean(j))* *(fctn(x,i,k,m)-xmean(k)) 71 free1=npts-1 72 sigma=dsqrt(sigma/free1) do 78 j=1,nterms 74 sigmax(j)=dsqrt(sigmax(j)/free1) r(j)=r(j)/(free1*sigmax(j)*sigma) do 78 k=1,j array(j,k)=array(j,k)/(free1*sigmax(j)*sigmax(k)) 78 array(k,j)=array(j,k) c c invert symmetric matrix c 81 call matinv (array,nterms,det) if (det) 101,91,101 91 a0=0. sigma0=0. rmul=0. chisqr=0. ftest=0. goto 150 c c calculate coefficients, fit, and chi square c 101 a0=ymean 102 do 108 j=1,nterms do 104 k=1,nterms 104 a(j)=a(j)+r(k)*array(j,k) 105 a(j)=a(j)*sigma/sigmax(j) 106 a0=a0-a(j)*xmean(j) 107 do 108 i=1,npts 108 yfit(i)=yfit(i)+a(j)*fctn(x,i,j,m) 111 do 113 i=1,npts yfit(i)=yfit(i)+a0 113 chisq=chisq+weight(i)*(y(i)-yfit(i))**2 freen=npts-nterms-1 115 chisqr=chisq*wmean/freen c c calculate uncertainties c 121 if (mode) 122,124,122 122 varnce=1./wmean goto 131 124 varnce=chisqr 131 do 133 j=1,nterms 132 sigmaa(j)=array(j,j)*varnce/(free1*sigmax(j)**2) if (sigmaa(j)) 835, 835, 836 835 sigmaa(j) = 0.0 goto 133 836 sigmaa(j)=sqrt(sigmaa(j)) 133 rmul=rmul+a(j)*r(j)*sigmax(j)/sigma freej=nterms c +noao: When rmul = 1, the following division (stmt 135) would blow up. c It has been changed so ftest is set to -99999. in this case. if (rmul) 935, 136, 136 935 ftest = -99999. rmul = -99999. goto 141 c -noao 136 if (1.0 - abs(rmul)) 1035, 1036, 1037 1035 rmul=-99999. ftest = -99999. goto 141 1036 ftest = -99999. rmul = 1.0 goto 141 1037 ftest=(rmul/freej)/((1.-rmul)/freen) rmul=sqrt(rmul) 141 sigma0=varnce/fnpts do 145 j=1,nterms do 145 k=1,nterms 145 sigma0=sigma0+varnce*xmean(j)*xmean(k)*array(j,k)/ *(free1*sigmax(j)*sigmax(k)) 146 sigma0=sqrt(sigma0) 150 return end