C Copyright 1981-2012 ECMWF.
C
C This software is licensed under the terms of the Apache Licence 
C Version 2.0 which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
C
C In applying this licence, ECMWF does not waive the privileges and immunities 
C granted to it by virtue of its status as an intergovernmental organisation 
C nor does it submit to any jurisdiction.
C

      INTEGER FUNCTION IRSCAN (PMAT, KLEN, KLLEN, KNNS, KSCAN, KPR,
     1   KERR)
C
C---->
C**** *IRSCAN*
C
C     PURPOSE
C     _______
C
C     This routine transforms a field between the specified external
C     scanning mode and a standard internal scanning mode where the
C     array represents a quasi regular field.
C
C     INTERFACE
C     _________
C
C     IERR = IRSCAN (PMAT, KLEN, KLLEN, KNNS, KSCAN, KPR, KERR)
C
C     Input parameters
C     ________________
C
C     PMAT       - The input matrix of length (KLEN).
C
C     KLEN       - The number of points in the matrix.
C
C     KLLEN      - This array contains the quasi regular Gaussian
C                  line length definitions.
C
C     KNNS       - The number of points in the North-South direction.
C
C     KSCAN      - A standard GRIB byte variable with bits 1 to 3
C                  separately significant. This means that the final
C                  value is the sum of the bit settings.
C
C                  128 , Set if points scan East to West.
C                   64 , Set if points scan South to North.
C                   32 , Set if points in the North South direction
C                        are consecutive.
C
C     KPR        - The debug print switch.
C                  0  , No debugging output.
C                  1  , Produce debugging output.
C
C     KERR       - The error control flag.
C                  -ve, No error message. Return error code.
C                  0  , Hard failure with error message.
C                  +ve, Print error message. Return error code.
C
C     Output parameters
C     ________________
C
C     PMAT       - The transposed matrix.
C
C     Return value
C     ____________
C
C     The error indicator (INTEGER).
C
C     Error and Warning Return Values
C     _______________________________
C
C     7201  The scanning mode was not in the range 0 to 255.
C     7202  A scanning mode with consecutive values in the North
C           South direction was requested. This is not compatible
C           with a quasi regular Gaussian field.
C     7203  The total number of points given by the array KLLEN was
C           not equal to KLEN.
C
C     Common block usage
C     __________________
C
C     None
C
C     EXTERNALS
C     _________
C
C     IRLREV     - Routine to reverse the elements within each row
C                  or each column of a quasi regular Gaussian field.
C     INTLOG     - Logs messages.
C
C     METHOD
C     ______
C
C     KSCAN = 128 is implemented by swapping elements within each
C                 column of the matrix.
C
C     KSCAN = 64  is implemented by reversing the order of the columns.
C
C     REFERENCE
C     _________
C
C     None
C
C     COMMENTS
C     ________
C
C     Program contains sections 0 to 2 and 9
C
C     AUTHOR
C     ______
C
C     K. Fielding      *ECMWF*      Jan 1994
C
C     MODIFICATIONS
C     _____________
C
C     None
C
C----<
C     _______________________________________________________
C
C
C*    Section 0. Definition of variables.
C     _______________________________________________________
C
C*    Prefix conventions for variable names
C
C     Logical      L (but not LP), global or common.
C                  O, dummy argument
C                  G, local variable
C                  LP, parameter.
C     Character    C, global or common.
C                  H, dummy argument
C                  Y (but not YP), local variable
C                  YP, parameter.
C     Integer      M and N, global or common.
C                  K, dummy argument
C                  I, local variable
C                  J (but not JP), loop control
C                  JP, parameter.
C     REAL         A to F and Q to X, global or common.
C                  P (but not PP), dummy argument
C                  Z, local variable
C                  PP, parameter.
C
C     Implicit statement to force declarations
C
      IMPLICIT NONE
C
#include "parim.h"
C
C     Dummy arguments
C
      INTEGER KLEN, KNNS, KSCAN, KPR, KERR
C
      INTEGER KLLEN (KNNS)
C
      REAL PMAT (KLEN)
C
C     Local variables
C
      LOGICAL GNSMOD, GWEMOD, GTRMOD
C
      INTEGER ISCAN, IDIR, ITOTAL, IERR
C
      INTEGER JSTEP
C
      INTEGER JPROUTINE
C
      PARAMETER (JPROUTINE = 7200)
C
C     External functions
C
      INTEGER IRLREV
C
C     _______________________________________________________
C
C
C*    Section 1. Initialisation - Evaluate scan modes
C     _______________________________________________________
C
  100 CONTINUE
C
      IF (KPR .GE. 1) CALL INTLOG(JP_DEBUG,'IRSCAN: Section 1.',JPQUIET)
C
      IRSCAN = 0
C
      IF (KPR .GE. 1) THEN
         CALL INTLOG(JP_DEBUG,'IRSCAN: Input parameters',JPQUIET)
         CALL INTLOG(JP_DEBUG,'IRSCAN: Total length of matrix is ',KLEN)
         CALL INTLOG(JP_DEBUG,'IRSCAN: Latitude lines are ',KNNS)
         CALL INTLOG(JP_DEBUG,'IRSCAN: Scan mode is ',KSCAN)
      ENDIF
C
      IF (KSCAN .LT. 0 .OR. KSCAN .GE. 256) THEN
         IRSCAN = JPROUTINE + 1
         IF (KERR .GE. 0) CALL INTLOG(JP_ERROR,
     X     'IRSCAN: Scan mode is not in range 0 to 255 = ',KSCAN)
         IF (KERR .EQ. 0) CALL INTLOG(JP_FATAL,
     X    'IRSCAN: Interpolation fails.',IRSCAN)
         GO TO 900
      ENDIF
C
C     Zero KSCAN means no transformation
C
      IF (KSCAN .EQ. 0) GO TO 900
C
      ISCAN = KSCAN
      GWEMOD = .FALSE.
      GNSMOD = .FALSE.
C
      IF (ISCAN .GE. 128) THEN
         ISCAN = ISCAN - 128
         GWEMOD = .TRUE.
      ENDIF
C
      IF (ISCAN .GE. 64) THEN
         ISCAN = ISCAN - 64
         GNSMOD = .TRUE.
      ENDIF
C
      GTRMOD = ISCAN .GE. 32
C
      IF (GTRMOD) THEN
        IRSCAN = JPROUTINE + 2
        IF (KERR .GE. 0) THEN
         CALL INTLOG(JP_ERROR,
     X     'IRSCAN: scan mode wants consecutive N to S points',JPQUIET)
           CALL INTLOG(JP_ERROR,
     X      'IRSCAN: Not feasible for a quasi regular grid',JPQUIET)
          IF (KERR .EQ. 0) CALL INTLOG(JP_FATAL,
     X      'IRSCAN: Interpolation fails.',IRSCAN)
        ENDIF
        GO TO 900
      ENDIF
C
      ITOTAL = 0
C
      DO 110 JSTEP = 1, KNNS
        ITOTAL = ITOTAL + KLLEN (JSTEP)
  110 CONTINUE
C
      IF (ITOTAL .NE. KLEN) THEN
        IRSCAN = JPROUTINE + 3
        IF (KERR .GE. 0) THEN
          CALL INTLOG(JP_ERROR,
     X      'IRSCAN: Array length provided = ',KLEN)
            CALL INTLOG(JP_ERROR,
     X       'IRSCAN: not equal to sum of line lengths = ',ITOTAL)
           IF (KERR .EQ. 0) CALL INTLOG(JP_FATAL,
     X       'IRSCAN: Interpolation fails.',IRSCAN)
         ENDIF
         GO TO 900
      ENDIF
C
C     _______________________________________________________
C
C*    Section 2. Any field as order is unimportant
C
C                Potential operations in order are
C
C                1 Modify West East mode
C                2 Modify North South mode
C     _______________________________________________________
C
  200 CONTINUE
C
      IF (KPR .GE. 1) CALL INTLOG(JP_DEBUG,'IRSCAN: Section 2.',JPQUIET)
C
      IF (GWEMOD) THEN
C
         IDIR = 1
C
         IERR = IRLREV (PMAT, KLEN, KLLEN, KNNS, IDIR, KPR)
C
         IF (IERR .GT. 0) THEN
            IRSCAN = IERR
            GO TO 900
         ENDIF
C
      ENDIF
C
      IF (GNSMOD) THEN
C
         IDIR = 2
C
         IERR = IRLREV (PMAT, KLEN, KLLEN, KNNS, IDIR, KPR)
C
         IF (IERR .GT. 0) THEN
            IRSCAN = IERR
            GO TO 900
         ENDIF
C
      ENDIF
C
C     _______________________________________________________
C
C*    Section 9. Return to calling routine. Format statements
C     _______________________________________________________
C
  900 CONTINUE
C
      IF (KPR .GE. 1) CALL INTLOG(JP_DEBUG,'IRSCAN: Section 9.',JPQUIET)
C
      RETURN
      END
