**==aa0001.f  
C
C PROGRAM 'DIFFLMRG'
C =================
C
C SORT AND MERGE A NUMBER OF 'DIFFLAUE' OUTPUT MTZ FILES
C FOR REFLECTIONS WITH MORE THAN ONE ENTRY, WEIGHTED AVERAGES
C ARE TAKEN FOR THE FL1 SIGL1 FL2 AND SIGL2 COLUMNS AND FOR
C THE PHASE AND WEIGHT COLUMNS (IF PRESENT) THE VALUES FOR
C THE FIRST ENTRY ARE TAKEN. THE PROGRAM ASSUMES THAT THE
C SAME COLUMNS ARE PRESENT IN EACH FILE AND THAT THEY ARE
C IN THE ORDER PRODUCED BY DIFFLAUE
C
C THE ARRAY IA(/AA) IS USED TO HOLD THE SETS OF LAUE DATA FOR SORTING
C AND MERGING. EACH REFLECTION OCCUPIES 7 WORDS AS FOLLOWS
C (WORD 1 INTEGER, REMAINDER REAL)
C        WORD 1  H,K,L,FILM PACKED  2**20(H+128)+2**12(K+128)+
C                                   2**4(L+128)+KFILM (KFILM=0 IN
C                                   THIS PROGRAM)
C        WORD 2  FL1
C        WORD 3  SIGL1
C        WORD 4  FL2
C        WORD 5  SIGL2
C        WORD 6  COLUMN 8 FROM INPUT MTZ FILE IF PRESENT
C        WORD 7  COLUMN 9 FROM INPUT MTZ FILE IF PRESENT
C
C PARAMETER STATEMENT  MXRF=MAX NO. OF REFLECTIONS ALLOWED
      PARAMETER(MXRF=50000)
C
C
C SPECIFICATION STATEMENTS
C ------------------------
C
      DIMENSION IA(7*MXRF),AA(7*MXRF)
      INTEGER ISORT(5)
      LOGICAL ONL,CCPONL,END,EOF
      CHARACTER*70 TITLE
      CHARACTER*80 HSTR(2)
      CHARACTER*7 LFIN
      DIMENSION LCOL(100),CELL(6),ADATA(100),IHKL(3)
      EQUIVALENCE (IA(1),AA(1))
      DATA LFIN/'HKLIN00'/
      DATA NTWO20/1048576/
      DATA NTWO12/4096/
      DATA NTWO4/16/
      DATA HSTR/'Created by DIFFLMRG program',' '/
      DATA ISORT/1,2,3,0,0/
C
C INITIALISATIONS
C ---------------
C
      IFAIL = 0
      CALL CCPOPN(5,'DATA',5,1,LDUM,IFAIL)
      CALL CCPOPN(6,'PRINTER',6,1,LDUM,IFAIL)
      CALL CCPVRS(6,'DIFFLMRG','15/10/92')
      ONL = CCPONL(IDUM)
      NREF = 0
      NSIGZ = 0
      IB = -7
      IAMAX = 7*MXRF
      CALL MTZINI
C
C READ IN CONTROL CARDS
C ---------------------
C
C DATA CARD 1   NFILES
C
      IF (ONL) WRITE (6,6040)
      READ (5,*) NFILES
      IF (NFILES.LT.2) THEN
C
C ERROR CONDITIONS
C ----------------
C
         WRITE (6,6070)
         STOP
      ELSE
C
C DATA CARD 2    TITLE FOR OUTPUT FILE
C
         IF (ONL) WRITE (6,6050)
         READ (5,6010) TITLE
C
C OPEN FIRST INPUT MTZ FILE AND OPEN OUTPUT MTZ FILE
C --------------------------------------------------
C
         NF = 1
         NN = 0
         CALL LROPEN (1,'HKLIN1',1,IFAIL)
         IF (IFAIL.EQ.1) STOP
         CALL LRNCOL (1,NCOLIN)
         IF (NCOLIN.LT.7 .OR. NCOLIN.GT.9) THEN
            WRITE (6,6120)
            STOP
         ELSE
            CALL LWOPEN(1,'HKLOUT')
            CALL LWHIST(1,HSTR,1)
            CALL LWSORT(1,ISORT)
C
C COPY REFLECTION RECORDS TO ARRAY 'IA/AA'
C
 20         CALL LRREFL(1,RESOL,ADATA,EOF)
            IF (EOF) GO TO 40
            IF (ADATA(5).LE.0.0 .OR. ADATA(7).LE.0.0) THEN
               NSIGZ = NSIGZ + 1
               GO TO 20
            END IF
            IB = IB + 7
            NREF = NREF + 1
            NN = NN + 1
            IF (NREF.GT.MXRF) GO TO 140
            IH = NINT(ADATA(1))
            IK = NINT(ADATA(2))
            IL = NINT(ADATA(3))
            IF (IH.LT.-127 .OR. IH.GT.127) GO TO 150
            IF (IK.LT.-127 .OR. IK.GT.127) GO TO 150
            IF (IL.LT.-127 .OR. IL.GT.127) GO TO 150
            IA(IB+1) = NTWO20*(IH+128) + NTWO12*(IK+128)
     +                 + NTWO4*(IL+128)
            DO 30 I = 4 , NCOLIN
               J = I - 2
               AA(IB+J) = ADATA(I)
 30         CONTINUE
            GO TO 20
         END IF
      END IF
 40   CALL LRCLOS(1)
      WRITE (6,6020) NF , NN
C
C LOOP THROUGH REMAINING INPUT MTZ FILES COPYING REFLECTION RECORDS
C -----------------------------------------------------------------
C
      DO 80 NF = 2 , NFILES
         NN = 0
         LFIN(6:7) = ' '
         IF (NF.LT.10) THEN
            WRITE (LFIN(6:6),'(I1)') NF
         ELSE
            WRITE (LFIN(6:7),'(I2.2)') NF
         END IF
         IUN = 10 + NF
         CALL LROPEN(2,LFIN,1,IFAIL)
         IF (IFAIL.EQ.1) STOP
         CALL LRNCOL(2,NCOL)
         IF (NCOL.NE.NCOLIN) GO TO 130
 50      CALL LRREFL(2,RESOL,ADATA,EOF)
         IF (EOF) GO TO 70
         IF (ADATA(5).LE.0.0 .OR. ADATA(7).LE.0.0) THEN
            NSIGZ = NSIGZ + 1
            GO TO 50
         END IF
         IB = IB + 7
         NREF = NREF + 1
         NN = NN + 1
         IF (NREF.GT.MXRF) GO TO 140
         IH = NINT(ADATA(1))
         IK = NINT(ADATA(2))
         IL = NINT(ADATA(3))
         IF (IH.LT.-127 .OR. IH.GT.127) GO TO 150
         IF (IK.LT.-127 .OR. IK.GT.127) GO TO 150
         IF (IL.LT.-127 .OR. IL.GT.127) GO TO 150
         IA(IB+1) = NTWO20*(IH+128) + NTWO12*(IK+128)
     +                 + NTWO4*(IL+128)
         DO 60 I = 4 , NCOLIN
            J = I - 2
            AA(IB+J) = ADATA(I)
 60      CONTINUE
         GO TO 50
 70      CALL LRCLOS(2)
         WRITE (6,6020) NF , NN
 80   CONTINUE
C
C SORT REFLECTION DATA ON H,K,L
C -----------------------------
C
      CALL REFSRT(IA,NREF,7,IAMAX)
C
C MERGE AND OUTPUT DATA
C ---------------------
C
      END = .FALSE.
      NROUT = 0
      NMULT = 0
      M1 = 1
      ILAST = IA(1)
      K = 0
C
C STEP THROUGH THE REFLECTIONS
C
 90   K = K + 1
      IF (K.GT.NREF) THEN
         END = .TRUE.
         GO TO 100
      END IF
      JJ = 7*K - 6
      IF (IA(JJ).EQ.ILAST) GO TO 90
 100  M2 = K - 1
      MM = 7*M1 - 6
      CALL GETHKL(IA(MM),IHKL,KDUM)
      ADATA(1) = IHKL(1)
      ADATA(2) = IHKL(2)
      ADATA(3) = IHKL(3)
      IF (NCOLIN.GT.7) ADATA(8) = AA(MM+5)
      IF (NCOLIN.GT.8) ADATA(9) = AA(MM+6)
      SIGW1 = 0
      SIGW2 = 0
      SIGWF1 = 0
      SIGWF2 = 0
      IF (M1.EQ.M2) THEN
         ADATA(4) = AA(MM+1)
         ADATA(5) = AA(MM+2)
         ADATA(6) = AA(MM+3)
         ADATA(7) = AA(MM+4)
      ELSE
         NMULT = NMULT + 1
         DO 110 M = M1 , M2
            IP = 7*(M-1)
            W1 = 1.0/(AA(IP+3)*AA(IP+3))
            W2 = 1.0/(AA(IP+5)*AA(IP+5))
            SIGW1 = SIGW1 + W1
            SIGW2 = SIGW2 + W2
            SIGWF1 = SIGWF1 + AA(IP+2)*W1
            SIGWF2 = SIGWF2 + AA(IP+4)*W2
 110     CONTINUE
         F1 = 0
         IF (SIGWF1.GT.0) F1 = SIGWF1/SIGW1
         W1 = SIGW1/(M2-M1+1)
         ADATA(4) = F1
         ADATA(5) = SQRT(1/W1)
         F2 = 0
         IF (SIGWF2.GT.0) F2 = SIGWF2/SIGW2
         W2 = SIGW2/(M2-M1+1)
         ADATA(6) = F2
         ADATA(7) = SQRT(1/W2)
      END IF
      CALL LWREFL(1,ADATA)
      NROUT = NROUT + 1
      IF (END) THEN
         CALL LWCLOS(1,1)
         WRITE (6,6060) NREF , NSIGZ , NMULT , NROUT
         STOP
      ELSE
         M1 = K
         ILAST = IA(JJ)
         GO TO 90
      END IF
  130  WRITE (6,6090)
      STOP
 140  WRITE (6,6100) MXRF
      STOP
 150  WRITE (6,6110) IH , IK , IL
      STOP
C
C FORMAT STATEMENTS
C -----------------
C
 6010 FORMAT (A)
 6020 FORMAT (/,' NUMBER OF REFLECTIONS READ FROM FILE',I3,' IS',I6)
 6030 FORMAT (//,' OUTPUT REFLECTION FILE COMPLETED')
 6040 FORMAT (/,' Number of input files?')
 6050 FORMAT (/,' Title for output MTZ file?')
 6060 FORMAT (//,' TOTAL  NUMBER  OF  REFLECTIONS  READ  IN  ',I6,/,
     +        ' NUMBER OF REFLECTIONS OMITTED WITH SIG=0  ',I6,/,
     +        ' NO. REFLECTIONS WITH MULTIPLE MEASUREMENTS',I6,/,
     +        ' NO. OF REFLECTIONS WRITTEN TO OUTPUT FILE ',I6,//)
C
 6070 FORMAT (/,' **A MINIMUM OF TWO INPUT FILES MUST BE SPECIFIED**')
 6090 FORMAT (/,' **NO. OF COLUMNS MISMATCH BETWEEN FILES**')
 6100 FORMAT (/,' **MAXIMUM OF',I7,' REFLECTIONS EXCEEDED**')
 6110 FORMAT (/,' **INDICES OUT OF RANGE -127 TO 127, HKL=',3I4,' **')
 6120 FORMAT (/,' **NUMBER OF COLUMNS INVALID FOR A DIFFLAUE O/P FILE**'
     +        )
      END
**==refsrt.f  
C
C SUBROUTINE 'REFSRT'
C ===================
C
C THIS SUBROUTINE IS USED TO SORT THE REFLECTION DATA HELD IN CORE. IT
C IS A MODIFIED VERSION OF THE SUBROUTINE 'AHVSOR' FROM ELEANOR DODSON'S
C VERSION OF THE PROGRAM 'CAD'. THIS VERSION SORTS ON A WORD CONTAINING
C THE PACKED INDICES.
C
      SUBROUTINE REFSRT(IA,NREF,NWRD,IDIM)
C
C PARAMETERS
C
C         IA (I/O)  INTEGER ARRAY CONTAINING THE REFLECTION DATA WITH
C                   NWRD WORDS FOR REFLN 1 FOLLOWED BY NWRD WORDS FOR
C                   EACH REFLECTION UP TO NREF REFLECTIONS  (NWRD <=10)
C       NREF (I)    THE NO. OF REFLECTIONS TO BE SORTED
C       NWRD (I)    NUMBER OF WORDS/REFLECTION (INDICES PACKED IN FIRST
C                   WORD FOR EACH REFLECTION)
C       IDIM (I)    THE NUMBER OF ELEMENTS IN THE ARRAY IA
C
C SPECIFICATION STATEMENTS
C ------------------------
C
      IMPLICIT INTEGER(A-Z)
      INTEGER IA(IDIM),ITEMP,CUT(10)
      INTEGER SAVE(2,16)
      DATA CUTOFF/20/
C
C SORT DATA
C ---------
C
      STACK = 0
      LOW = 1
      HIGH = NREF
 20   CHUNK = HIGH - LOW
      IF (CHUNK.GT.CUTOFF) THEN
         MIDDLE = (LOW+HIGH)/2
         IF (ICMP(IA,LOW,IA,MIDDLE).GT.0) THEN
            J1 = NWRD*(LOW-1)
            J2 = NWRD*(MIDDLE-1)
            DO 30 I = 1 , NWRD
               J1 = J1 + 1
               J2 = J2 + 1
               ITEMP = IA(J1)
               IA(J1) = IA(J2)
               IA(J2) = ITEMP
 30         CONTINUE
         END IF
         IF (ICMP(IA,MIDDLE,IA,HIGH).GT.0) THEN
            J1 = NWRD*(MIDDLE-1)
            J2 = NWRD*(HIGH-1)
            DO 40 I = 1 , NWRD
               J1 = J1 + 1
               J2 = J2 + 1
               ITEMP = IA(J1)
               IA(J1) = IA(J2)
               IA(J2) = ITEMP
 40         CONTINUE
            IF (ICMP(IA,LOW,IA,MIDDLE).GT.0) THEN
               J1 = NWRD*(LOW-1)
               J2 = NWRD*(MIDDLE-1)
               DO 50 I = 1 , NWRD
                  J1 = J1 + 1
                  J2 = J2 + 1
                  ITEMP = IA(J1)
                  IA(J1) = IA(J2)
                  IA(J2) = ITEMP
 50            CONTINUE
            END IF
         END IF
         J = NWRD*(MIDDLE-1)
         DO 60 I = 1 , NWRD
            J = J + 1
            CUT(I) = IA(J)
 60      CONTINUE
         UP = LOW
         DOWN = HIGH
 70      DOWN = DOWN - 1
         IF (ICMP(CUT,1,IA,DOWN).LT.0) GO TO 70
 80      UP = UP + 1
         IF (ICMP(CUT,1,IA,UP).GT.0) GO TO 80
         IF (UP.LT.DOWN) THEN
            J1 = NWRD*(UP-1)
            J2 = NWRD*(DOWN-1)
            DO 90 I = 1 , NWRD
               J1 = J1 + 1
               J2 = J2 + 1
               ITEMP = IA(J1)
               IA(J1) = IA(J2)
               IA(J2) = ITEMP
 90         CONTINUE
            GO TO 70
         ELSE IF (UP.EQ.DOWN) THEN
            DOWN = DOWN - 1
            UP = UP + 1
         END IF
      ELSE
         IF (CHUNK.GE.2) THEN
            MM = HIGH - 1
            DO 120 M = LOW , MM
               MIN = M
               MMM = M + 1
               DO 100 N = MMM , HIGH
                  IF (ICMP(IA,MIN,IA,N).GT.0) THEN
                     MIN = N
                  END IF
 100           CONTINUE
               IF (MIN.NE.M) THEN
                  J1 = NWRD*(M-1)
                  J2 = NWRD*(MIN-1)
                  DO 110 I = 1 , NWRD
                     J1 = J1 + 1
                     J2 = J2 + 1
                     ITEMP = IA(J1)
                     IA(J1) = IA(J2)
                     IA(J2) = ITEMP
 110              CONTINUE
               END IF
 120        CONTINUE
         END IF
         IF (STACK.EQ.0) RETURN
         LOW = SAVE(1,STACK)
         HIGH = SAVE(2,STACK)
         STACK = STACK - 1
         GO TO 20
      END IF
      STACK = STACK + 1
      IF (STACK.GT.16) THEN
C
C ERROR CONDITION
C ----------------
C
         WRITE (6,6010) STACK
         STOP
      ELSE
         BOTTOM = DOWN - LOW
         TOP = HIGH - UP
         IF (BOTTOM.GT.TOP) THEN
            SAVE(1,STACK) = LOW
            SAVE(2,STACK) = DOWN
            LOW = UP
         ELSE
            SAVE(1,STACK) = UP
            SAVE(2,STACK) = HIGH
            HIGH = DOWN
         END IF
         GO TO 20
      END IF
C
C FORMAT STATEMENTS
C -----------------
C
 6010 FORMAT (' **STACK LIMIT OF 16 EXCEEDED IN REFSOR**')
      END
**==icmp.f  
C
C FUNCTION 'ICMP'
C ===============
C
C THIS FUNCTION IS USED TO COMPARE THE VALUES OF THE SORT KEYS
C FOR 2 REFLECTIONS  (ASSUMES 7 WORDS/REFLECTION)
C
      FUNCTION ICMP(IARR1,I1,IARR2,I2)
C
C PARAMETERS
C
C        IARR1 (I)   ARRAY CONTAINING 1ST REFLN
C           I1 (I)   POINTER TO REFLECTION IN IARR1
C        IARR2 (I)   ARRAY CONTAINING 2ND REFLN
C           I2 (I)   POINTER TO REFLECTIONIIN IARR2
C
C FUNCTION RETURN VALUES  -1  REFLN 1 LT REFLN 2
C                          0  REFLN 1 EQ REFLN 2
C                          1  REFLN 1 GT REFLN 2
C
C SPECIFICATION STATEMENTS
C ------------------------
C
      INTEGER IARR1(*),IARR2(*)
C
C COMPARE KEYS
C ------------
C
      J1 = 7*I1 - 6
      J2 = 7*I2 - 6
      IF (IARR1(J1).LT.IARR2(J2)) THEN
         ICMP = -1
         RETURN
      ELSE IF (IARR1(J1).EQ.IARR2(J2)) THEN
         ICMP = 0
         RETURN
      ELSE
         ICMP = 1
         RETURN
      END IF
      END
**==gethkl.f  
C
C SUBROUTINE 'GETHKL'
C ===================
C
C THIS SUBROUTINE UNPACKS THE INDICES FOR A LAUE REFLECTION
C
      SUBROUTINE GETHKL(IDX,IDXL,KFILM)
C
C PARAMETERS
C
C      IDX (I)   WORD CONTAINING PACKED INDICES
C     IDXL (O)   3 WORD ARRAY CONTAINING H, K, L.
C    KFILM (O)   FILM NUMBER (1 TO 6)
C
C SPECIFICATION STATEMENTS
C ------------------------
C
      DIMENSION IDXL(3)
      DATA NTWO20/1048576/
      DATA NTWO16/65536/
      DATA NTWO12/4096/
      DATA NTWO4/16/
C
C UNPACK INDICES
C --------------
C
      I = IDX
      IDXL(1) = I/NTWO20
      I = I - NTWO20*IDXL(1)
      IDXL(1) = IDXL(1) - 128
      IDXL(2) = I/NTWO12
      I = I - NTWO12*IDXL(2)
      IDXL(3) = I/NTWO4
      KFILM = I - NTWO4*IDXL(3)
      IDXL(2) = IDXL(2) - 128
      IDXL(3) = IDXL(3) - 128
      RETURN
      END
