	SUBROUTINE SOLVIT(A,Y,R,X,W,V,B,M,N,NR,IE,LUN)
C REVISED DEC 4,78
C
C  FOR LINEAR LEAST-SQUARES CURVE FITTING OR SIMULTANEOUS SOLUTION
C  TO LINEAR EQUATIONS
C-----------------------------------------------------------------------
C  DESCRIPTION OF PARAMETERS --
C   A--   TWO-DIMENSIONAL ARRAY, LENGTH M BY N, BUT DIMENSION IT NR BY
C          THE MAXIMUM VALUE OF N.
C         FOR CURVE FITTING, A IS THE INDEPENDENT-VARIABLE MATRIX,
C          E.G. FOR THE CURVE  LOG Y = X1 + X2/T + X3 *LOG T  PUT
C          1.0,1.0/T(1), AND LOG(T(1)) IN THE 1ST 3 COL. OF ROW 1,
C          1.0,1.0/T(2), AND LOG(T(2)) IN THE 1ST 3 COL. OF ROW 2,
C          ETC., FOR M DATA SETS THERE WILL BE M ROWS AND N IS 3.
C         FOR THE SIMULTANEOUS SOLUTION, EACH ROW CONTAINS THE
C          COEFFICIENTS FOR A PARTICULAR EQUATION.
C   Y--   ONE-DIMENSIONAL ARRAY OF LENGTH M, BUT DIMENSION IT NR.
C          FOR CURVE FITTING,STORE THE DEPENDENT VARIABLES
C          OR THEIR TRANSFORMS.
C          FOR SIMULTANEOUS SOLUTION STORE THE CONSTANT TERMS.
C   R--   ONE-DIMENSIONAL ARRAY OF LENGTH M, BUT DIMENSION IT NR.
C          SOLVIT STORES THE RESIDUALS, THE DIFFERENCE BETWEEN
C          INPUT Y VALUES AND CALCULATED VALUES.
C   X--   ONE-DIMENSIONAL ARRAY, LENGTH N.  DIMENSION IT MAXIMUM N.
C          FOR CURVE FITTING,X IS THE ARRAY OF COEFFICIENTS.
C          FOR SIMULTANEOUS SOLUTION,X IS THE SOLUTION ARRAY.
C   W,V,B  ARE ONE-DIMENSIONAL WORKING ARRAYS, DIMENSION RESPECTIVELY
C          NR,NR, AND NR TIMES THE MAXIMUM VALUE OF M.
C        TO SAVE CORE SPACE, THESE ARRAYS MAY BE EQUIVALENCED TO ARRAYS
C        USED ONLY BEFORE OR AFTER CALLING SOLVIT, E.G. YCALC.
C  THE SUM OF RESIDUALS SQUARED APPEARS IN THE FIRST WORD OF ARRAY B.
C
C CONSTANTS
C   M--   NUMBER OF ROWS BEING USED IN MATRIX A.
C   N--   NUMBER OF COLUMNS BEING USED IN MATRIX A.
C   NR--  NUMBER OF ROWS MATRIX A IS DIMENSIONED IN CALLING PROGRAM.
C   IE--  ERROR CODE-- 0-NO ERROR, 1- ERROR STATEMENT WRITTEN
C
C   TYPICAL DIMENSION AND CALL STATEMENTS
C      TO FIT TO A MAXIMUM OF 250 DATA PAIRS AND A MAXIMUM OF 10 TERMS
C          REAL A(250,10),Y(250),R(250),X(10),W(250),V(250),B(2500)
C          CALL SOLVIT(A,Y,R,X,W,V,B,N,M,250,IE)
C      TO SOLVE A MAXIMUM OF 80 SIMULTANEOUS EQUATIONS
C          REAL A(80,80),Y(80),R(80),X(80),W(80),V(80),B(6400)
C          CALL SOLVIT(A,Y,R,X,W,V,B,N,N,80,IE)
C
C  DEVELOPED BY A. R. MILLER
C-----------------------------------------------------------------------
C
	REAL A(NR,1),Y(1),R(1),X(1),W(1),V(1),B(1)
C
	IE = 0
	IF (N .GT. M) GO TO 304
	DO 10 I = 1, M
	DO 10 J = 1, N
	LL = (J - 1) * M + I
10	B(LL) = A(I,J)
	DO 70  I=1, N
	IIA = (I - 1) * M
	T = 0.
	DO 20  K = I, M
	LL = IIA + K
20	T = T + B(LL) * B(LL)
	IF (T .EQ. 0.0) GO TO 300
	LL = IIA + I
C	W(I) = SIGN(ST , B(LL))
	W(I) = SQRT(T)
	IF (B(LL) .LT. 0.0) W(I)= -W(I)
	B(LL) = B(LL) + W(I)
	V(I) = - B(LL) * W(I)
	IF (I .EQ. N) GO TO 75
	IP = I + 1
	DO 70  J = IP, N
	JIA = (J - 1) * M
	T = 0.
	DO 40  K = I, M
	LL = IIA + K
	LLL = JIA + K
40	T = T + B(LL) * B(LLL)
	T = T / V(I)
	DO 70  L = I , M
	LL = JIA + L
	LLL = IIA + L
70	B(LL) = B(LL) + T * B(LLL)
75	S = 0.
	DO 100 L = 1, M
	R(L)=Y(L)
100	S = S + R(L) * R(L)
	DO 102 I = 1, N
102	X(I) = 0.
	YE = S
105	DO 130 I = 1, N
	IIA = (I - 1) * M
	T = 0.
	DO 110 K = I, M
	LL = IIA + K
110	T = T + B(LL) * R(K)
	T = T / V(I)
	DO 120 L = I, M
	LL = IIA + L
120	R(L) = R(L) + T * B(LL)
130	CONTINUE
	IN = N
	DO 190 I = 1, N
	R(IN) = R(IN) / W(IN)
	INM = IN - 1
	LLIN = INM * M
	J = INM
	DO 155 L = 1, INM
	LL = LLIN + J
	R(J) = R(J) + R(IN) * B(LL)
155	J = J - 1
190	IN = IN - 1
	DO 210 I = 1, N
210	X(I) = X(I) - R(I)
	DO 230 I = 1, M
	RD = Y(I)
	DO 220 J = 1, N
220	RD = RD - A(I,J) * X(J)
	R(I) = RD
230	CONTINUE
	RE = 0.
	DO 240 I = 1, M
240	RE = RE + R(I) * R(I)
	IF (RE .GE. S) GO TO 270
	S = RE
	GO TO 105
270	B(1) = RE
	IF (RE .LT. YE) RETURN
	WRITE (LUN,1001)
	GO TO 390
300	WRITE (LUN,1002)
	GO TO 390
304	WRITE (LUN,1003)
390	IE = 1
	RETURN
1001	FORMAT('0SOLVIT ERROR--R.GT.Y,'
     * ' LOOK FOR WRONG VALUES IN MATRIX')
1002	FORMAT(30H0SOLVIT ERROR--MATRIX SINGULAR)
1003	FORMAT(37H0SOLVIT ERROR--MORE COLUMNS THAN ROWS)
	END
	SUBROUTINE PPLOT(X,Y,YCALC,N,LI,ILINES)
C NOV 14,78  NARROW WIDTH
C-------------------------------------------------------------------
C  PURPOSE--
C   PRODUCE A PLOT ON THE LINE PRINTER OF ONE OR TWO ONE-DIMENSIONAL
C   ARRAYS, E.G., Y AND YCALC, AS A FUNCTION OF A THIRD ONE-DIMENSIONAL
C   ARRAY, E,G., X.  ARRAYS MUST BE ARRANGED IN ASCENDING OR DESCENDING
C   ORDER OF INDEPENDENT VARIABLE X.
C
C
C  DESCRIPTION OF PARAMETERS
C    X -- ARRAY OF INDEPENDENT VARIABLES.
C    Y -- ARRAY OF DEPENDENT VARIABLES, X SYMBOL,OR M WHEN MULTIPLE.
C    YCALC-- ARRAY OF CALCULATED DEPENDENT VARIABLES, * SYMBOL.
C    N -- LENGTH OF ARRAYS X,Y, AND YCALC BEING USED.
C	  MAKE N NEGATIVE IF ONLY X AND Y ARE TO BE PLOTTED.
C	  YCALC IS THEN A DUMMY VARIABLE.
C    LI - LOGICAL UNIT NUMBER FOR OUTPUT
C    ILINES - NUMBER OF LINES FOR PLOT
C
C  WRITTEN BY ALAN R. MILLER
C--------------------------------------------------------------------
C
	REAL X(1),Y(1),YCALC(1),YLABEL(6)
	INTEGER	OUT(51),PLUS,STAR,BLANK,MULT
	DATA IPLUS/1H+/,STAR/1H*/,BLANK/1H /,MULT/1HM/,LINEL/51/
	JF(P)=IFIX((P-YMIN)/YSCALE+1.0)
C
	LINES=MAX0(ILINES,MIN0(N,200))
C	GOTO 1
C	ENTRY PPLOTL(X,Y,YCALC,N,JLINE)
C	LINES=JLINE
1	LONE=0
	PLUS=IPLUS
	IF (N.GT.0) GOTO 2
C  IF N IS NEGATIVE PLOT ONLY X AND Y
	N=-N
	LONE=1
	PLUS=STAR
	WRITE(LI,100) N,PLUS,MULT
2	XLOW=X(1)
	IF (LONE.EQ.0) WRITE(LI,101) N,PLUS,STAR,MULT
	XHI=X(N)
	YMAX=Y(1)
	YMIN=YMAX
	XSCALE=(XHI-XLOW)/FLOAT(LINES-1)
	IF (LONE.EQ.1) GOTO 5
	DO 3 I=1,N
	YMIN=AMIN1(YMIN,Y(I),YCALC(I))
3	YMAX=AMAX1(YMAX,Y(I),YCALC(I))
	GOTO 7
5	DO 6 I=1,N
	YMIN=AMIN1(YMIN,Y(I))
6	YMAX=AMAX1(YMAX,Y(I))
7	YSCALE=(YMAX-YMIN)/50
	YS10=YSCALE*10.0
	YLABEL(1)=YMIN
	DO 9  KN=1,4
9	YLABEL(KN+1)=YLABEL(KN)+YS10
	YLABEL(6)=YMAX
	IPRINT=0
	IF (ABS(XHI).GE.1.E5.OR. ABS(XHI).LT.1.E-2)  IPRINT=1
	DO 10 I=1,LINEL
10	OUT(I)=BLANK
C  FIRST LINE.
	JP=JF(Y(1))
	OUT(JP)=PLUS
	IF (LONE.EQ.1) GOTO 12
	JP=JF(YCALC(1))
	OUT(JP)=STAR
12	L=1
	XLABEL=XLOW
	ISKIP=0
	DO 80 I=2,LINES
	XNEXT =XLOW+XSCALE*FLOAT(I-1)
	IF (ISKIP.EQ.1) GOTO 25
13	L=L+1
	CHANGE=XNEXT-0.5*XSCALE
	IF ((X(L)-CHANGE)*SIGN(1.0,XSCALE).GT.0.0) GOTO 30
C  MULTIPLE POINT
	JP=JF(Y(L))
	IF (OUT(JP).EQ.PLUS.OR.OUT(JP).EQ.MULT) GOTO 15
	OUT(JP)=PLUS
	GOTO 20
15	OUT(JP)=MULT
20	IF (LONE.EQ.1) GOTO 13
	JP=JF(YCALC(L))
	OUT(JP)=STAR
	GOTO 13
C  SKIP LINE
25	WRITE(LI,103)
	GOTO 40
C  PRINT LINE.
30	DO 31 IX=1,LINEL
	JX = LINEL-IX+1
	IF (OUT(JX).NE.BLANK) GOTO 32
31	CONTINUE
	JX = 1
32	IF (IPRINT.EQ.0) WRITE (LI,104) XLABEL,(OUT(IX),IX=1,JX)
	IF (IPRINT.EQ.1) WRITE (LI,102) XLABEL,(OUT(IX),IX=1,JX)
	DO 35 IX=1,LINEL
35	OUT(IX)=BLANK
40	CHANGE=XNEXT + 0.5*XSCALE
	IF ((X(L)-CHANGE)*SIGN(1.0,XSCALE).LT.0.0) GOTO 50
	ISKIP=1
	GOTO 80
50	ISKIP=0
	XLABEL=XNEXT
	JP=JF(Y(L))
	OUT(JP)=PLUS
	IF (LONE.EQ.1) GOTO 80
	JP=JF(YCALC(L))
	OUT(JP)=STAR
80	CONTINUE
81	IF (L.GE.N) GOTO 90
C  MULTIPLE POINT FOR LAST LINE
	L=L+1
	JP=JF(Y(L))
	IF (OUT(JP).EQ.PLUS.OR.OUT(JP).EQ.MULT) GOTO 83
	OUT(JP)=PLUS
	GOTO 81
83	OUT(JP)=MULT
	GOTO 81
90	DO 91 IX=1,LINEL
	JX = LINEL-IX+1
	IF (OUT(JX).NE.BLANK) GOTO 92
91	CONTINUE
	JX = 1
92	IF (IPRINT.EQ.0) WRITE (LI,104) XHI,(OUT(IX),IX=1,JX)
	IF (IPRINT.EQ.1) WRITE (LI,102) XHI,(OUT(IX),IX=1,JX)
	WRITE (LI,107)
	IF (ABS(YMAX).LT.1.E4.AND.ABS(YMAX).GE.1.E-2) GOTO 96
	WRITE (LI,106) YLABEL
	GOTO 97
96	WRITE (LI,108) YLABEL
97	WRITE (LI,109)
	RETURN
100	FORMAT(1H1,I3,10H DATA SETS,6X,
     $ A1,7H-DATA, ,A1,15H-MULTIPLE POINT/)
101	FORMAT(1H1,I3,10H DATA SETS,6X,
     $ A1,7H-DATA, ,A1,15H-FITTED CURVE, ,A1,15H-MULTIPLE POINT/)
102	FORMAT(1X ,1PE11.4,5X,101A1)
103	FORMAT(1X)
104	FORMAT(1X ,F11.4,5X,101A1)
106	FORMAT(1H0,8X,1P11E10.2)
107	FORMAT(17X,5(1H.9X),1H.)
108	FORMAT(1H0,9X,11F10.4)
109	FORMAT(/30X,18HDEPENDENT VARIABLE)
	END
	SUBROUTINE SORT2(X,Y,N)
C
C SHELL-METZNER SORT
C
	REAL X(1),Y(1)
C
	IREV = 0
	IF (N .GT. 0) GOTO 5
	N = -N
	IREV = 1
5	J4 = N
10	J4 = J4 / 2
	IF (J4.EQ.0) RETURN
	J2 = N - J4
	J = 1
20	I = J
30	J3 = I + J4
	IF (IREV .EQ. 0 .AND. X(I) .LE. X(J3)) GOTO 40
	IF (IREV .EQ. 1 .AND. X(I) .GE. X(J3)) GOTO 40
	HOLD = X(I)
	X(I) = X(J3)
	X(J3) = HOLD
	HOLD = Y(I)
	Y(I) = Y(J3)
	Y(J3) = HOLD
	I = I - J4
	IF (I .GE. 1) GOTO 30
40	J = J + 1
	IF (J .GT. J2) GOTO 10
	GOTO 20
	END
      SUBROUTINE SQUARE(A,B,M,N,NA,MB,E,F,G)
C  PROGRAM TO CONVERT CURVE FITTING DATA ARRAY TO SQUARE ARRAY
C  OBTAIN B = TRANSPOSE A * A
C
C  A - M-BY-N CURVE-FITTING ARRAY
C  B - N-BY-N SQUARE ARRAY, A TRANSPOSE * A
C  M - ROWS OF A
C  N - COLUMNS OF A
C  NA- NUMBER OF ROWS ARRAY A IS DIMENSIONED
C  NB- NUMBER OF ROWS ARRAY B IS DIMENSIONED
C  E - DUMMY ARRAY, LENGTH M*M
C  F,G DUMMY ARRAYS, LENGTH M
C
C SUBROUTINE MATINV IS NEEDED
C
	REAL A(NA,1),B(MB,1),E(1),F(1),G(1)
C
	DO 50 K=1,N
	DO 50 L=1,K
	B(K,L)=0.0
	DO 30 I=1,M
30	B(K,L)=B(K,L)+A(I,L)*A(I,K)
	IF (K.NE.L) B(L,K)=B(K,L)
50	CONTINUE
C  INVERT MATRIX B
	CALL MATINV(B,N,MB,E,F,G)
	RETURN
	END
	SUBROUTINE MATINV(B,N,NR,A,L,M)
C
C PURPOSE - TO INVERT A MATRIX
C
C  B - ORIGINAL N-BY-N MATRIX, REPLACED BY INVERSE
C  N - ORDER OF MATRIX
C  NR- NUMBER OF ROWS B IS DIMENSIONED
C  D - RESULTANT DETERMINANT
C  A - WORK ARRAY, LENGTH N*N
C  L,M - WORK ARRAYS, LENGTH N
C
	DIMENSION B(NR,1),A(1),L(1),M(1)
C
C CONVERT SQUARE ARRAY B TO LINEAR ARRAY A
C
	K=0
	DO 5 J=1,N
	DO 5 I=1,N
	K=K+1
5	A(K)=B(I,J)
C
C SEARCH FOR LARGEST ELEMENT
C
	D=1.0
	NK=-N
	DO 80 K=1,N
	NK=NK+N
	L(K)=K
	M(K)=K
	KK=NK+K
	BIGA=A(KK)
	DO 20 J=K,N
	IZ=N*(J-1)
	DO 20 I=K,N
	IJ=IZ+I
10	IF(ABS(BIGA)- ABS(A(IJ))) 15,20,20
15	BIGA=A(IJ)
	L(K)=I
	M(K)=J
20	CONTINUE
C
C INTERCHANGE ROWS
C
	J=L(K)
	IF(J-K) 35,35,25
25	KI=K-N
	DO 30 I=1,N
	KI=KI+N
	HOLD=-A(KI)
	JI=KI-K+J
	A(KI)=A(JI)
30	A(JI) =HOLD
C
C INTERCHANGE COLUMNS
C
35	I=M(K)
	IF(I-K) 45,45,38
38	JP=N*(I-1)
	DO 40 J=1,N
	JK=NK+J
	JI=JP+J
	HOLD=-A(JK)
	A(JK)=A(JI)
40	A(JI) =HOLD
C
C DIVIDE COLUMN BY MINUS PIVOT
C PIVOT IS CONTAINED IN BIGA
C
45	IF(BIGA) 48,46,48
46	D=0.0
	RETURN
48	DO 55 I=1,N
	IF(I-K) 50,55,50
50	IK=NK+I
	A(IK)=A(IK)/(-BIGA)
55	CONTINUE
C
C REDUCE MATRIX
C
	DO 65 I=1,N
	IK=NK+I
	IJ=I-N
	DO 65 J=1,N
	IJ=IJ+N
	IF(I-K) 60,65,60
60	IF(J-K) 62,65,62
62	KJ=IJ-I+K
	A(IJ)=A(IK)*A(KJ)+A(IJ)
65	CONTINUE
C
C DIVIDE ROW BY PIVOT
C
	KJ=K-N
	DO 75 J=1,N
	KJ=KJ+N
	IF(J-K) 70,75,70
70	A(KJ)=A(KJ)/BIGA
75	CONTINUE
C
C PRODUCT OF PIVOTS
C
C *** DONT USE D
C	D=D*BIGA
C
C REPLACE PIVOT BY RECIPROCAL
C
	A(KK)=1.0/BIGA
80	CONTINUE
C
C FINAL ROW AND COLUMN INTERCHANGE
C
	K=N
100	K=K-1
	IF(K) 150,150,105
105	I=L(K)
	IF(I-K) 120,120,108
108	JQ=N*(K-1)
	JR=N*(I-1)
	DO 110 J=1,N
	JK=JQ+J
	HOLD=A(JK)
	JI=JR+J
	A(JK)=-A(JI)
110	A(JI) =HOLD
120	J=M(K)
	IF(J-K) 100,100,125
125	KI=K-N
	DO 130 I=1,N
	KI=KI+N
	HOLD=A(KI)
	JI=KI-K+J
	A(KI)=-A(JI)
130	A(JI) =HOLD
	GOTO 100
C
C CONVERT INVERTED MATRIX A TO N-BY-N MATRIX B
C
150	K=0
	DO 160 J=1,N
	DO 160 I=1,N
	K=K+1
160	B(I,J)=A(K)
	RETURN
	END
	SUBROUTINE LINFIT(X,Y,YC,R,N,A,B,COR,SA,SB)
C LINEAR FIT Y=A + B*X, CORR. COEFF
C STD ERROR ON A AND B
C
	REAL X(1),Y(1),YC(1),R(1)
C
	SUMX  = 0
	SUMY  = 0
	SUMXY = 0
	SUMY2 = 0
	SUMX2 = 0
	DO 10 I=1,N
	XI = X(I)
	YI = Y(I)
	SUMX = SUMX+XI
	SUMY = SUMY+YI
	SUMXY = SUMXY + XI*YI
	SUMX2 = SUMX2 + XI*XI
10	SUMY2 = SUMY2 + YI*YI
	DENOM = SUMX2 - SUMX*SUMX/N
	C = SUMXY - SUMX*SUMY/N
	B = C/DENOM
	A = (SUMY - B*SUMX)/N
	COR = C / SQRT(DENOM * (SUMY2 - SUMY*SUMY / N))
	SEE = SQRT((SUMY2 - A*SUMY - B*SUMXY) / (N-2))
	SB = SEE / SQRT(DENOM)
	SA = SB * SQRT(SUMX2/N)
	DO 20 I=1,N
	YC(I) = A + B * X(I)
	R(I) = Y(I) - YC(I)
20	CONTINUE
	RETURN
	END
