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 IGSCAN (PMAT, KNWE, KNNS, KSCAN, OINFIELD,
     1   KPR, KERR)
C
C---->
C**** *IGSCAN*
C
C     PURPOSE
C     _______
C
C     Transform a regular field between the specified external
C     scanning mode and a standard internal scanning mode.
C
C     INTERFACE
C     _________
C
C     IERR = IGSCAN (PMAT, KNWE, KNNS, KSCAN, OINFIELD, KPR, KERR)
C
C     Input parameters
C     ________________
C
C     PMAT       - The input matrix of dimension (KNWE * KNNS).
C
C     KNWE       - The number of points in the West-East direction.
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     OINFIELD   - Flag variable which is TRUE for an input field and
C                  FALSE for an output field.
C                  This determines the order in which the
C                  transformations are applied.
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     7101  The scanning mode was not in the range 0 to 255.
C
C     Common block usage
C     __________________
C
C     None
C
C     EXTERNALS
C     _________
C
C     ABORTX     - Standard routine to kill task.
C     IGTRAN	 - Routine to transpose a rectangular matrix.
C     IGLREV     - Routine to reverse the elements within each row or
C                  each column of a rectangular matrix.
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     KSCAN = 32 is implemented by transposing the matrix.
C
C     An input matrix is transposed before the two reversal stages
C     are performed.
C
C     An output matrix has the matrix transposition as the final step.
C
C     REFERENCE
C     _________
C
C     None
C
C     COMMENTS
C     ________
C
C     Program contains sections 0 to 3 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
      LOGICAL OINFIELD
C
      INTEGER KNWE, KNNS, KSCAN, KPR, KERR
C
      REAL PMAT (KNWE * KNNS)
C
C     Local variables
C
      LOGICAL GNSMOD, GWEMOD, GTRMOD
C
      INTEGER ISCAN, IDIR, IERR
C
      INTEGER JPMOVE
      PARAMETER (JPMOVE = (JPLAT + JPLONG) / 2)
C
      INTEGER IMOVE (JPMOVE)
C
      INTEGER JPROUTINE
C
      PARAMETER (JPROUTINE = 7100)
C
C     External functions
C
      INTEGER IGTRAN, IGLREV
C
C     _______________________________________________________
C
C
C*    Section 1. Initialisation - Evaluate scan modes
C     _______________________________________________________
C
  100 CONTINUE
C
      IF (KPR .GE. 1) CALL INTLOG(JP_DEBUG,'IGSCAN: Section 1.',JPQUIET)
C
      IGSCAN = 0
C
      IF (KPR .GE. 1) THEN
         CALL INTLOG(JP_DEBUG,'IGSCAN: Input parameters',JPQUIET)
         CALL INTLOG(JP_DEBUG,'IGSCAN: Longitude points are ',KNWE)
         CALL INTLOG(JP_DEBUG,'IGSCAN: Latitude lines are ',KNNS)
         CALL INTLOG(JP_DEBUG,'IGSCAN: Scan mode is ',KSCAN)
         IF ( OINFIELD ) THEN
           CALL INTLOG(JP_DEBUG,
     X       'IGSCAN: Input field transformation is TRUE',JPQUIET)
         ELSE
           CALL INTLOG(JP_DEBUG,
     X       'IGSCAN: Input field transformation is FALSE',JPQUIET)
         ENDIF
      ENDIF
C
      IF (KSCAN .LT. 0 .OR. KSCAN .GE. 256) THEN
         IGSCAN = JPROUTINE + 1
         IF (KERR .GE. 0) CALL INTLOG(JP_ERROR,
     X    'IGSCAN: Scan mode is not in range 0 to 255 = ',KSCAN)
         IF (KERR .EQ. 0) CALL INTLOG(JP_FATAL,
     X    'IGSCAN: Interpolation fails.',IGSCAN)
         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
C     _______________________________________________________
C
C*    Section 2. Input field
C
C                Potential operations in order are
C
C                1 Transpose matrix
C                2 Modify West East mode
C                3 Modify North South mode
C     _______________________________________________________
C
  200 CONTINUE
C
      IF (KPR .GE. 1) CALL INTLOG(JP_DEBUG,'IGSCAN: Section 2.',JPQUIET)
C
      IF (OINFIELD) THEN
C
         IF (GTRMOD) THEN
C
            IERR = IGTRAN (PMAT, KNNS, KNWE, IMOVE, JPMOVE, KPR, KERR)
C
            IF (IERR .NE. 0) THEN
               IGSCAN = IERR
               GO TO 900
            ENDIF
C
         ENDIF
C
         IF (GWEMOD) THEN
C
            IDIR = 1
C
            IERR = IGLREV (PMAT, KNWE, KNNS, IDIR, KPR, KERR)
C
            IF (IERR .NE. 0) THEN
               IGSCAN = IERR
               GO TO 900
            ENDIF
C
         ENDIF
C
         IF (GNSMOD) THEN
C
            IDIR = 2
C
            IERR = IGLREV (PMAT, KNWE, KNNS, IDIR, KPR, KERR)
C
            IF (IERR .NE. 0) THEN
               IGSCAN = IERR
               GO TO 900
            ENDIF
C
         ENDIF
C
      ELSE
C
C     _______________________________________________________
C
C*    Section 3. Output field
C
C                Potential operations in order are
C
C                1 Modify West East mode
C                2 Modify North South mode
C                3 Transpose matrix
C     _______________________________________________________
C
  300 CONTINUE
C
      IF (KPR .GE. 1) CALL INTLOG(JP_DEBUG,'IGSCAN: Section 3.',JPQUIET)
C
         IF (GWEMOD) THEN
C
            IDIR = 1
C
            IERR = IGLREV (PMAT, KNWE, KNNS, IDIR, KPR, KERR)
C
            IF (IERR .NE. 0) THEN
               IGSCAN = IERR
               GO TO 900
            ENDIF
C
         ENDIF
C
         IF (GNSMOD) THEN
C
            IDIR = 2
C
            IERR = IGLREV (PMAT, KNWE, KNNS, IDIR, KPR, KERR)
C
            IF (IERR .NE. 0) THEN
               IGSCAN = IERR
               GO TO 900
            ENDIF
C
         ENDIF
C
         IF (GTRMOD) THEN
C
            IERR = IGTRAN (PMAT, KNWE, KNNS, IMOVE, JPMOVE, KPR, KERR)
C
            IF (IERR .NE. 0) THEN
               IGSCAN = IERR
               GO TO 900
            ENDIF
C
         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,'IGSCAN: Section 9.',JPQUIET)
C
      RETURN
      END
