CFTN7X,Q,T,S C$CDS ON c INCLUDE 'CALPGM.INC' C supplimentary routines for CALFIT : SUBFIT.FOR C C Copyright (C) 1989, California Institute of Technology C All rights reserved. U. S. Government Sponsorship under C NASA Contract NAS7-918 is acknowledged. C C Herbert M. Pickett, 24 Feb 1989 C SUBROUTINE GETLBL(IDPAR,PARLBL,LU,FIL,IDIV) C C gets parameter label from user file C C IDPAR = list of parameter ID numbers , IDPAR(0) = number of parameters C PARLBL = returned list of parameter labels C LU = unit to use for user file C FIL = file name to use for userfile C IDIV = divisor for vibrational field C INTEGER LU,IDIV REAL*8 IDPAR(0:*) CHARACTER*(*) PARLBL(*),FIL CHARACTER*64 FNAM INTEGER NPAR,IBGN,KNT,I,JDIV C EMA IDPAR C INTEGER*4 IDTMP,JDTMP CHARACTER*30 PARX NPAR=IDPAR(0) IBGN=1 KNT=NPAR C .. initialize labels DO 1 I=1,NPAR 1 PARLBL(I)=' ' FNAM=FIL C .. open file of parameter names 2 CALL OPENLU(LU,FNAM,'RL') C .. first line contains divisor to ignore lower digits of ID READ(LU,*,END=99,ERR=99) JDIV JDIV=MAX(JDIV,1) C C DO until EOF C 20 READ(LU,'(I10,A)',END=99,ERR=99) JDTMP,PARX C .. negative ID signals that parameter name field is a new file C to find further parameter names IF ( JDTMP. LT.0 ) THEN CALL OPENLU(LU,FNAM,'C') FNAM=PARX GO TO 2 ENDIF JDTMP=JDTMP/JDIV DO 10 I=IBGN,NPAR IDTMP=ABS(IDPAR(I))/IDIV+0.5 IF (JDTMP.EQ.IDTMP) THEN IF (PARLBL(I).EQ.' ') THEN PARLBL(I)=PARX IF (I.EQ.IBGN) IBGN=IBGN+1 KNT=KNT-1 ENDIF ENDIF 10 CONTINUE IF (KNT.GT.0) GO TO 20 99 CALL OPENLU(LU,FNAM,'C') RETURN END SUBROUTINE GETBLK(IBLK,INDX,IQNUM,NBLKPF,IPOS,NQN) INTEGER IBLK,INDX,NBLKPF,IPOS,NQN,IQNUM(6) C C gets block (IBLK) and INDEX from quantum numbers (IQNUM) C C C NBLKPF IS THE NUMBER OF BLOCKS PER "F" C IPOS IS THE POSITION IN IQNUM TO FIND "F" C NQN IS THE NUMBER OF QUANTUM NUMBERS C INTEGER I0,NSIZE,KQNUM(6),IQNF,IBGN,IDBLK,NCOD,IDGN, : NN,KBGN,K,KDTAU,KK,NBLK PARAMETER (I0=0) INDX=0 IBLK=0 C ..check for indication of null level IF (IQNUM(1).LT.0) RETURN IQNF=IQNUM(IPOS) IBGN=IQNF NBLK=NBLKPF IF(IQNF.LT.0) THEN IBGN=-IBGN K=10-IBGN IF(K.GT.1) NBLK=NBLK*K ENDIF IBGN=IBGN*NBLKPF IQNUM(IPOS)=IQNUM(1) C ..loop over blocks for given F DO 10 IDBLK=1,NBLK IBLK=IBGN+IDBLK CALL GETQN(IBLK,I0,KQNUM,NSIZE,NCOD) INDX = 1 C ..search for match within block C DO WHILE(INDX.LE.NSIZE) 30 IF (INDX.LE.NSIZE) THEN CALL GETQN(IBLK,INDX,KQNUM,IDGN,NCOD) KQNUM(IPOS)=KQNUM(1) NN=ABS(NCOD) C ..NN is the size of a wang sub-block C ..NCOD < 0 if oblate basis C IF (NN.LE.1) THEN NN=1 KBGN=2 ELSE KBGN=4 ENDIF DO 20 K=NQN,KBGN,-1 IF(IQNUM(K).NE.KQNUM(K)) GO TO 15 20 CONTINUE C ..all quanta tested equal IF (NN.EQ.1) GO TO 100 C ..assignment could be in this sub-block KDTAU=IQNUM(2)-IQNUM(3)-KQNUM(2)+KQNUM(3) KK=KDTAU/4 IF (KK*4.EQ.KDTAU) THEN C ..symmetry is good IF (NCOD.LT.0) KK=-KK IF (KK.GE.0.AND.KK.LT.NN) THEN C ..value is in range INDX=INDX+KK GO TO 100 ENDIF ENDIF C ..to get here, quanta were not right 15 INDX=INDX+NN GO TO 30 ENDIF C END DO 10 CONTINUE C ..no match found IBLK=0 NBLK=0 C .. standard return 100 IF(NBLK.GT.NBLKPF) IQNF=IQNF-(IBLK-IBGN-1)/NBLKPF IQNUM(IPOS)=IQNF IF(IQNF.LT.0) INDX=-INDX RETURN END SUBROUTINE DTRI(T,LDT,N,NS) INTEGER LDT,N,NS REAL*8 T(LDT,1) C EMA T C C DTRDI COMPUTES THE DETERMINANT AND INVERSE OF A REAL C TRIANGULAR MATRIX. C C ON ENTRY C C T REAL(LDT,N) C T CONTAINS THE LOWER TRIANGULAR MATRIX. THE ZERO C ELEMENTS OF THE MATRIX ARE NOT REFERENCED, AND C THE CORRESPONDING ELEMENTS OF THE ARRAY CAN BE C USED TO STORE OTHER INFORMATION. C NS ADDITIONAL ROWS USED FOR Y VECTORS C C LDT INTEGER C LDT IS THE LEADING DIMENSION OF THE ARRAY T. C C N INTEGER C N IS THE ORDER OF THE SYSTEM. C C NS INTEGER C NS IS THE NUMBER OF SOLUTION VECTORS C ON RETURN C C T INVERSE OF ORIGINAL MATRIX PLUS SOLUTIONS C C C ADAPTED FROM LINPACK. C C SUBROUTINES AND FUNCTIONS C C BLAS DAXPY,DSCAL C C INTERNAL VARIABLES C REAL*8 TEMP INTEGER J,K,I1,NT PARAMETER (I1=1) C NT=NS C .. COMPUTE INVERSE OF LOWER TRIANGULAR C DO 150 K = N ,1, -1 TEMP = 1 / T(K,K) T(K,K) = TEMP CALL DSCAL(NT,TEMP,T(K+1,K),I1) NT=NT+1 DO 130 J = 1, K - 1 TEMP = -T(K,J) T(K,J) = 0 CALL DAXPY(NT,TEMP,T(K,K),I1,T(K,J),I1) 130 CONTINUE 150 CONTINUE RETURN END SUBROUTINE FILBAK(LU,FLU,LUBAK,FBAK) C make backup par file with / in column 80 C LU = input file unit number C FLU= input file name (.par) C LUBAK=backup file unit number C FBAK =backup file name (.bak) C INTEGER LU,LUBAK,K CHARACTER*(*) FLU,FBAK CHARACTER*80 CLINE CALL OPENLU(LU,FLU,'R') CALL OPENLU(LUBAK,FBAK,'WP') 10 READ(LU,100,END=50) CLINE DO 15 K=80,1,-1 IF(CLINE(K:K).NE.' ') THEN WRITE(LUBAK,100) CLINE(1:K) GO TO 10 ENDIF 15 CONTINUE GO TO 10 50 CALL OPENLU(LU,FLU,'C') CALL OPENLU(LUBAK,FBAK,'C') 100 FORMAT(A) RETURN END SUBROUTINE PRCORR(LUFIT,NPAR,COR,NDCOR,ERR,IDPAR) INTEGER LUFIT,NPAR,NDCOR,J,I1,N,NDEL,I,NPARTOT REAL*8 COR(NDCOR,*),ERR(*),IDPAR(0:*),DDOT,VAL C calculates and prints correlation coefficients PARAMETER (I1=1) C EMA VAR,ERPAR NPARTOT=IDPAR(0) NDEL=NPAR+1 I=0 DO 400 J=1,NPARTOT IF(IDPAR(J).GE.0) THEN I=I+1 VAL=1./ERR(J) N=NDEL-I CALL DSCAL(N,VAL,COR(I,I),I1) ENDIF 400 CONTINUE DO 480 I=NPAR,1,-1 N=NDEL-I DO 470 J=1,I 470 COR(J,I)=DDOT(N,COR(I,J),I1,COR(I,I),I1) 480 CONTINUE DO 490 I=2,NPAR N=I-1 CALL DCOPY(N,COR(I1,I),I1,COR(I,I1),NDCOR) 490 CONTINUE WRITE (LUFIT,690) ((I,J,COR(J,I),J=1,NPAR),I=1,NPAR) RETURN 690 FORMAT (8(2I3,F10.6)) END C$EMA // SUBROUTINE DNUADD(NPAR,NPARX,INITL,INDX,IFAC,EGY, : EGYDER,NSIZE,LINE,PAR,FAC) C subroutine to add energies and derivatives to frequency lists C ON INPUT: C NPAR = number of parameters C NPARX = number of parameters if INDX < 0 C INITL = first energy computed for this frequency IF < 0 C INDX = index in energy list C IFAC = scaling for energies C EGY = energy vector C EGYDER = energy derivative C NSIZE = column size of EGYDER C LINE = line counter for frequency derivatives in the heap C PAR = parameters C FAC = scaling values C INTEGER NPAR,NPARX,INITL,INDX,IFAC,NSIZE,LINE REAL*8 FAC(0:3),EGY(*),EGYDER(*),PAR(*), : HEAP(0:9000),DDOT,F,ZERO(2) INTEGER*4 NDEL,LDNUDP,LBUFOF INTEGER RDWRIT,I0,I1,NPARN,NOFF,ITMP PARAMETER (RDWRIT=0,I0=0,I1=1) COMMON HEAP SAVE ZERO DATA ZERO/0.,0./ C EMA PAR,EGY,EGYDER C.................. LDNUDP=LBUFOF(RDWRIT,LINE) NDEL=NPAR+LDNUDP IF (INITL.LT.0) HEAP(NDEL)=0 F=FAC(IFAC) C C ..add derivatives IF (INDX.LT.0) THEN C ..set up to ignore last few derivatives INDX=-INDX NPARN=NPARX NOFF=NPAR-NPARN ITMP=INDX+NPARN*NSIZE C ..add energies subtracting effect of ignored derivatives HEAP(NDEL)=HEAP(NDEL)+F*(EGY(INDX)- : DDOT(NOFF,EGYDER(ITMP),NSIZE,PAR(NPARN+1),I1)) IF (INITL.LT.0) CALL DCOPY(NOFF,ZERO,I0,HEAP(LDNUDP+NPARN),I1) ELSE NPARN=NPAR C ..add energies HEAP(NDEL)=HEAP(NDEL)+F*EGY(INDX) ENDIF C .. sum derivatives IF (INITL.LT.0) THEN CALL DCOPY(NPARN,EGYDER(INDX),NSIZE,HEAP(LDNUDP),I1) IF(IFAC.NE.0) CALL DSCAL(NPARN,F,HEAP(LDNUDP),I1) ELSE CALL DAXPY(NPARN,F,EGYDER(INDX),NSIZE,HEAP(LDNUDP),I1) ENDIF RETURN END C$EMA // SUBROUTINE DNUGET(IFLG,NPAR,F,LINE,DVEC) C subroutine to get derivatives and add to DVEC C ON INPUT: C IFLG = flag to determine type of operation C NPAR = number of parameters C F = scale factor (if IFLG <> 0 ) C LINE = line counter for frequency derivatives in the heap C RETURNS: C F = frequency ( if IFLG = 0 ) C DVEC = modified vector of derivatives and frequency C INTEGER IFLG,NPAR,LINE REAL*8 F,DVEC(*),HEAP(0:9000) INTEGER*4 LDNUDP,LBUFOF INTEGER I1,RDFLG PARAMETER (I1=1,RDFLG=1) COMMON HEAP C EMA DVEC C.................. LDNUDP=LBUFOF(RDFLG,LINE) IF (IFLG.GT.0) THEN C .. copy scaled derivatives into DVEC CALL DCOPY(NPAR,HEAP(LDNUDP),I1,DVEC,I1) CALL DSCAL(NPAR,F,DVEC,I1) ELSE IF (IFLG.LT.0) THEN C .. sum scaled derivatives with DVEC CALL DAXPY(NPAR,F,HEAP(LDNUDP),I1,DVEC,I1) ELSE C .. get calculated frequency F=HEAP(LDNUDP+NPAR) ENDIF RETURN END C FUNCTION LBUFOF(IFLG,IPOS) C C FUNCTION TO HANDLE ADDRESSES IN HEAP , WITH POSSIBLE STORE C INTEGER*4 LBUFOF,KDEL,IORG,RDORG LOGICAL REWRIT INTEGER IFLG,IPOS,BPOS,RELPOS,NEXT,NBUF,NREAD,NSAVE, & MAXREC,INC,NPOS,LU,K SAVE NEXT,KDEL,BPOS,NBUF,IORG,MAXREC,INC,LU,REWRIT DATA MAXREC/0/ C.................. IF(IFLG.LE.1.AND.IFLG.GE.-2) THEN C .. find offset from buffer origin, IFLG = -2, -1, 0, 1 NPOS=IPOS RELPOS=NPOS-BPOS NSAVE=NEXT NREAD=1 IF(RELPOS.GE.NEXT) THEN IF(RELPOS.LT.NBUF) THEN K=RELPOS-NEXT+1 IF(K.LE.INC) THEN C record nearly next in buffer NREAD=K NSAVE=0 NPOS=NEXT+BPOS RDORG=KDEL*NEXT NEXT=RELPOS+1 ENDIF ENDIF IF(IPOS.GT.MAXREC) THEN MAXREC=IPOS NREAD=NREAD-1 ENDIF ELSE IF(RELPOS.GE.0) THEN C record within buffer NSAVE=0 NREAD=0 ENDIF C .. save old data IF(NSAVE.GT.0) THEN IF(REWRIT) CALL DSAVE(LU,KDEL,BPOS,NSAVE) BPOS=NPOS RDORG=0 LBUFOF=0 NEXT=1 REWRIT=.FALSE. ELSE LBUFOF=KDEL*RELPOS ENDIF IF(ABS(IFLG).NE.1) REWRIT=.TRUE. IF(NREAD.GT.0) CALL DGET(LU,KDEL,RDORG,NPOS,NREAD) IF(IFLG.LT.0) LBUFOF=LBUFOF+IORG ELSE IF(IFLG.EQ.-4) THEN C .. save record length KDEL=IPOS C .. compute read grouping (1024 bytes) INC=128/IPOS+1 C .. return record length LBUFOF=KDEL ELSE IF(IFLG.EQ.-3) THEN C .. save origin IORG=IPOS LBUFOF=IORG ELSE IF(IFLG.EQ.-5) THEN C .. initialize C IPOS is blank common size in records NBUF=IPOS IF(MAXREC.EQ.0) THEN LU=-1 NEXT=0 BPOS=1 REWRIT=.FALSE. ELSE IF(NEXT.GT.NBUF) THEN C .. more records now than new size IF(REWRIT.OR.LU.LT.0) CALL DSAVE(LU,KDEL,BPOS,NEXT) NEXT=NBUF REWRIT=.FALSE. ENDIF C .. return maximum number of lines LBUFOF=NBUF ENDIF RETURN END C$EMA // SUBROUTINE DSAVE(LU,RLEN,KREC,NREC) C C FUNCTION TO SAVE HEAP C INTEGER LU,KREC,NREC INTEGER*4 RLEN,LBGN INTEGER IOS,I REAL*8 HEAP(0:9000) COMMON HEAP C C SAVE HEAP TO DISK C.................. IF(LU.LT.0) THEN LU=RLEN CALL OPENLU(LU,'Heap Scratch','S') ENDIF LBGN=-1 5 IF(NREC.LE.0) RETURN WRITE(LU,REC=KREC,ERR=9,IOSTAT=IOS) (HEAP(LBGN+I),I=1,RLEN) NREC=NREC-1 LBGN=LBGN+RLEN KREC=KREC+1 GO TO 5 C 9 WRITE(*,*) ' Heap write ERROR, IOSTAT=',IOS STOP 'Aborted' END C$EMA // SUBROUTINE DGET(LU,RLEN,IORG,KREC,NREC) C C FUNCTION TO READ HEAP C INTEGER LU,KREC,NREC INTEGER*4 RLEN,IORG INTEGER IOS,I REAL*8 HEAP(0:9000) COMMON HEAP C C GET HEAP FROM DISC IORG=IORG-1 10 READ(LU,REC=KREC,ERR=19,IOSTAT=IOS) (HEAP(IORG+I),I=1,RLEN) NREC=NREC-1 IF(NREC.LE.0) RETURN IORG=IORG+RLEN KREC=KREC+1 GO TO 10 C 19 WRITE(*,*) ' Heap read ERROR, IOSTAT=',IOS STOP 'Aborted' END C C this set of subroutines manipulates a record structure C of mixed type. the record elements are: C C 1. DNUDP = freq. derivatives (REAL*8 VECTOR) C 2. CFRQ = calc. frequency (REAL*8) C 3. XFRQ= line frequency (REAL*8) C 4. XWT = weight of line (REAL*8) C 5. XERR= error of line (REAL*8) C 6. LINKU=link to next upper state (INTEGER*2) 1 C 7. LINKL=link to next lower state (INTEGER*2) 2 C 8. IBU = upper state block number (INTEGER*2) 3 C 9. INU = upper state index number (INTEGER*2) 4 C 10. IBL = lower state block number (INTEGER*2) 5 C 11. INL = lower state index number (INTEGER*2) 6 C 12. IBLN= blend flag (INTEGER*2) 7 C 11. IQN = quantum number input (INTEGER*2) *12 8 ... 19 C SUBROUTINE HEAPNU(NPAR,NLIM) INTEGER NPAR INTEGER*4 NLIM C .. set up heap information for MAIN C ON INPUT: C NPAR = NUMBER OF PARAMETERS C NLIM = LENGTH OF BLANK COMMON IN REAL*8 UNITS C ON RETURN: C NLIM = POSITION OF IBU ELEMENT OF RECORD INTEGER*4 LBUFOF,IADR INTEGER NDBLE,IDM PARAMETER (IDM=19) C NDBLE returns number of REAL*8 words for number of C INTEGER*2 words C IDM is the number of INTEGER*2 values to be saved INTEGER I,NDEL,IORG,IVAL C.................. IORG=NPAR+4 C .. save origin I=-3 IORG=LBUFOF(I,IORG) NDEL=IORG+NDBLE(IDM) C .. save record length , return size of heap sub-blocks I=-4 NDEL=LBUFOF(I,NDEL) IADR=NLIM/NDEL IF(IADR.LT.2) IADR=2 C .. fix maximum buffer size I=-5 IVAL=IADR IF(LBUFOF(I,IVAL).LT.0) THEN IVAL=1 I=LBUFOF(IVAL,IVAL) ENDIF NLIM=IADR*NDEL RETURN END C$EMA // SUBROUTINE GETDBK(LINK,II,IBLK,INDX,INITL,IFAC) INTEGER LINK,II,IBLK,INDX,INITL,IFAC C C find data for line = abs(LINK) neg sign points to lower C returns II = line number C IBLK= requested block number C INDX= requested index C INITL < 0 if first block C IFAC= code for energy conversion C 0 for 1., 1 for -1., 2 for c, 3 for -c INTEGER*4 LBUFOF,IADR INTEGER*2 LVEC(6) INTEGER RDORG,I1,I6 PARAMETER (I1=1,I6=6,RDORG=-1) REAL*8 HEAP(0:9000),LVECD(2) COMMON HEAP C EMA LVEC EQUIVALENCE (LVECD,LVEC) C.................. II=ABS(LINK) IADR=LBUFOF(RDORG,II) CALL ICOPY(I1,I6,HEAP(IADR),LVECD) INITL=LVEC(3)-LVEC(5) IF(LINK.GE.0) THEN LINK=LVEC(1) IBLK=LVEC(3) INDX=LVEC(4) IF(INITL.EQ.IBLK.OR.INITL.EQ.0) INITL=-1 IFAC=0 ELSE LINK=LVEC(2) IBLK=LVEC(5) INDX=LVEC(6) INITL=-INITL IFAC=1 ENDIF C if XERR < 0 use cm-1 IF(HEAP(IADR-1).LT.0.) IFAC=IFAC+2 RETURN END C$EMA // SUBROUTINE FRQDAT(II,IBLN,XFRQ,XWT,XERR,IQN) INTEGER II,IBLN,IQN(12) REAL*8 XFRQ,XWT,XERR C .. gets blend code, frequency, weight, error , and quantum numbers INTEGER*4 LBUFOF,IADR INTEGER RDORG,LBLND,NT,I PARAMETER (LBLND=7,RDORG=-1,NT=19) INTEGER*2 LVEC(NT) REAL*8 HEAP(0:9000),LVECD(2) COMMON HEAP C EMA LVEC EQUIVALENCE (LVECD,LVEC) C.................. IADR=LBUFOF(RDORG,II) CALL ICOPY(LBLND,NT,HEAP(IADR),LVECD) IBLN=LVEC(LBLND) XFRQ=HEAP(IADR-3) XWT= HEAP(IADR-2) XERR=HEAP(IADR-1) DO 11 I=1,12 11 IQN(I)=LVEC(I+LBLND) RETURN END C$EMA // SUBROUTINE SAVDAT(II,LKU,LKL,IBU,INU,IBL,INL,IBLN, : XFRQ,XWT,XERR,IQN) INTEGER II,LKU,LKL,IBU,INU,IBL,INL,IBLN,IQN(12) REAL*8 XFRQ,XWT,XERR C .. saves block numbers, indices, blend code, frequency, weight, C .. error , and quantum numbers INTEGER*4 LBUFOF,IADR INTEGER WRDORG,I1,NT,I PARAMETER (WRDORG=-2,I1=1,NT=19) INTEGER*2 LVEC(NT) REAL*8 HEAP(0:9000),LVECD(2) C EMA LVEC COMMON HEAP EQUIVALENCE (LVECD,LVEC) C.................. IADR=LBUFOF(WRDORG,II) LVEC(1)=LKU LVEC(2)=LKL LVEC(3)=IBU LVEC(4)=INU LVEC(5)=IBL LVEC(6)=INL LVEC(7)=IBLN DO 21 I=1,12 21 LVEC(I+7)=IQN(I) CALL ICOPY(I1,NT,LVECD,HEAP(IADR)) HEAP(IADR-3)=XFRQ HEAP(IADR-2)=XWT HEAP(IADR-1)=XERR RETURN END C$EMA // SUBROUTINE SAVXWT(II,XWT,IBLN) INTEGER II,IBLN REAL*8 XWT C .. renormalize weight and update blend code INTEGER*4 LBUFOF,IADR REAL*8 HEAP(0:9000),LVECD(2) INTEGER*2 LVEC(19) INTEGER WRDORG,LBLND PARAMETER (WRDORG=-2,LBLND=7) C EMA LVEC COMMON HEAP EQUIVALENCE (LVECD,LVEC) C.................. IADR=LBUFOF(WRDORG,II) LVEC(LBLND)=IBLN CALL ICOPY(LBLND,LBLND,LVECD,HEAP(IADR)) HEAP(IADR-2)=HEAP(IADR-2)/XWT RETURN END C$EMA // INTEGER FUNCTION LNLINK(HEAD,PRVBLK,NBLK,IBLK,LINE,PLINK,FLG) C find place to insert link for line C return pointer to next line C C PRVBLK contains pointer to last line using given block C INTEGER*2 PRVBLK(*),LVEC(19) INTEGER HEAD,NBLK,IBLK,LINE,PLINK,FLG,LFLG,I,IBGN,LAST,NOW INTEGER*4 LBUFOF,IADR INTEGER WRDORG PARAMETER (WRDORG=-2) REAL*8 HEAP(0:9000),LVECD(2) COMMON HEAP C EMA LVEC EQUIVALENCE (LVECD,LVEC) C.................. IF(IBLK.LE.0) THEN LNLINK=0 RETURN ENDIF C search down for non zero element of PRVBLK LFLG=FLG IBGN=IBLK IF(IBGN.GT.NBLK) IBGN=NBLK DO 20 I=IBGN,1,-1 LAST=PRVBLK(I) IF(LAST.NE.0) GO TO 30 20 CONTINUE 30 PRVBLK(IBGN)=LINE IF(LAST.EQ.0) THEN LNLINK=HEAD HEAD=LINE IF(LFLG.EQ.0) RETURN LFLG=0 LAST=LINE NOW=LNLINK ELSE IF(LAST+LINE.EQ.0.AND.LFLG.EQ.0) THEN C special case of in-line link LNLINK=PLINK PLINK=LINE RETURN ELSE NOW=LINE ENDIF 40 IF(LAST.GE.0) THEN IBGN=1 I=LAST ELSE IBGN=2 I=-LAST ENDIF IADR=LBUFOF(WRDORG,I) CALL ICOPY(IBGN,IBGN,HEAP(IADR),LVECD) LNLINK=LVEC(IBGN) LVEC(IBGN)=NOW CALL ICOPY(IBGN,IBGN,LVECD,HEAP(IADR)) IF(LFLG.EQ.0) RETURN LAST=LINE NOW=LNLINK LFLG=0 GO TO 40 END