      SUBROUTINE MODIA(Q,RSDL, IOFF)

C     Given a 4x4 Q-matrix Q and a residual vector RSDL, MODIA searches
C     for a set of offsets in the integer-cycle ambiguities that will
C     generate the observed residual vector within some error.  Each
C     integer-cycle offset must be -9, 0, or +9 cycles.  The offsets
C     found are returned in the vector IOFF.
C     MODIA looks first for an acceptable IOFF in which only one
C     element is non-zero; if it finds such a solution, it will return
C     that solution without looking further.

C     Input Arguments:
C        Q(4,4) [R*8]: Input Q-matrix
C        RSDL(4) [R*8]: Input vector of observed L1 double-differenced
C                       phase residuals, in meters.
C     Output Argument:
C        IOFF(4) [I*4]: Vector containing the integer-cycle errors that
C                       will generate the observed residuals.


      IMPLICIT REAL*8 (A-H,O-Z)

      PARAMETER (MAXSAT = 10)                ! Maximum number of satellites
      PARAMETER (MAXPRS = MAXSAT - 1)        ! maximum number of sat. pairs

      DIMENSION IOFF(4),Q(MAXPRS,*),RESL(4),RSDL(*)

      PARAMETER (FREQ1 = 1.57542D9, C = 2.99792458D8)
      PARAMETER (WVLTH1 = C/FREQ1)

      DATA FMINF /0.0125D0/            ! Threshold for single-offset solution
                                       ! (in units of 9 cycles)

      DO  I=1,4
         IOFF(I) = 0                   ! Initialize output array
         RESL(I) = RSDL(I)/WVLTH1      ! Convert residuals to L1 cycles
      END DO
                              ! TRY A SINGLE_ELEMENT SOLUTION
      RMAX = -1.0D0        ! Look for the residual with the largest magnitude
      DO  I=1,4                        ! Init. magnitude, iterate on element
         ABSR = DABS(RSDL(I))
         IF (ABSR.GT.RMAX)  THEN       ! This residual is biggest so far
            RMAX = ABSR                ! Save its value
            IRMAX = I                  ! and location
         END IF
      END DO
                        ! FIND THE OFFSET THAT GIVES THE BEST MATCH
      FMIN = 1.0D0                  ! Init. min. diff. in units of 9 cycles
      REST = RESL(IRMAX)            ! The single residual we try to reproduce
      DO  I=1,4                     ! Try each pair in turn
         F = REST/(9.0D0*Q(IRMAX,I))   ! Offset that zeros rsdls., units of
         JF = JIDNNT(F)                ! 9 cycles; nearest integer
         F = DABS(F - JF)              ! Error as a fraction of 9 cycles
         IF (F.LT.FMIN)  THEN          ! This is the best so far
            FMIN = F                   ! Save the error
            IMIN = I                   ! and its location
            JJF = JF
         END IF
      END DO
                              ! RETURN SINGLE-OFFSET SOLUTION OR LOOK FURTHER
      IF (FMIN.LE.FMINF)  THEN         ! Single-offset solution is OK
         IOFF(IMIN) = 9*JJF            ! Put value in output array
         WRITE(6,'(T6,''MODIA: BEST CORRECTION IS ['',4I3,''].'')' )
     2      IOFF
         RETURN
      ELSE                             ! Have to try 81 possibilities
         C1 = Q(IRMAX,1)               ! Save the elements of the
         C2 = Q(IRMAX,2)               ! IRMAX-th row of Q in a
         C3 = Q(IRMAX,3)               ! convenient form
         C4 = Q(IRMAX,4)
         RMIN = 1.0D10                 ! Init. error
         K = -1                        ! Init. counter
         DO  I1=-1,1                   ! Iterate on offsets in integer-cycle
            DO  I2=-1,1                ! corrections for pairs 1, 2, 3,
               DO  I3=-1,1             ! and 4, in units of 9 cycles
                  DO  I4=-1,1
                     K = K + 1         ! Increment counter
                     R = 9.0D0*(C1*I1 + C2*I2 + C3*I3 + C4*I4) ! Comp. offset
                     DR = DABS(R - REST)     ! Our residual minus the actual
                     IF (DR.LT.RMIN)  THEN   ! The best so far
                        RMIN = DR            ! Save the offset
                        IK = K               ! and the corresponding counter
                     END IF
                  END DO
               END DO
            END DO
         END DO
                  ! CONVERT THE COUNTER TO OFFSETS (ERRORS) IN INTEGER CYCLES
         DO  I=4,1,-1
            IOFF(I) = 9*(IK - 3*(IK/3) - 1)  ! Use the counter to reproduce
            IK = IK/3                        ! the values of I4, I3, I2, and
         END DO                              ! I1, and convert to units of
      END IF                                 ! cycles
      WRITE(6,'(T6,''MODIA: BEST CORRECTION IS ['',4I3,''].'')' )  IOFF

      RETURN
      END
