C @(#)tdsearch1.for	19.1 (ES0-DMD) 02/25/03 14:11:20
C===========================================================================
C Copyright (C) 1995 European Southern Observatory (ESO)
C
C This program is free software; you can redistribute it and/or 
C modify it under the terms of the GNU General Public License as 
C published by the Free Software Foundation; either version 2 of 
C the License, or (at your option) any later version.
C
C This program is distributed in the hope that it will be useful,
C but WITHOUT ANY WARRANTY; without even the implied warranty of
C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
C GNU General Public License for more details.
C
C You should have received a copy of the GNU General Public 
C License along with this program; if not, write to the Free 
C Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
C MA 02139, USA.
C
C Corresponding concerning ESO-MIDAS should be addressed as follows:
C	Internet e-mail: midas@eso.org
C	Postal address: European Southern Observatory
C			Data Management Division 
C			Karl-Schwarzschild-Strasse 2
C			D 85748 Garching bei Muenchen 
C			GERMANY
C===========================================================================
C
C++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
C
C.IDENTIFICATION
C
C  TDSEARCH1.FOR              2.0   17OCT1985
C                            2.1   25OCT1985
C  J.D.PONZ                     ESO - GARCHING
C
C.KEYWORDS
C
C  TABLE, SEARCH
C
C.PURPOSE
C
C  SEARCHING IN TABLE COLUMNS USING TWO REAL OR DOUBLE PRECISION VALUES
C
C.INPUT/OUTPUT
C
C       TBES1D(TID, COLUMN, VALUE, ROW, ACTVAL, STATUS)
C       TBES1I(TID, COLUMN, VALUE, ROW, ACTVAL, STATUS)
C       TBES1R(TID, COLUMN, VALUE, ROW, ACTVAL, STATUS)
C       TBES2D(TID, COLUMN1, COLUMN2, VALUE, ROW, ACTVAL, STATUS)
C       TBES2I(TID, COLUMN1, COLUMN2, VALUE, ROW, ACTVAL, STATUS)
C       TBES2R(TID, COLUMN1, COLUMN2, VALUE, ROW, ACTVAL, STATUS)
C
C.ALGORTIHM
C
C   USE THE EUCLIDEAN DISTANCE
C
C------------------------------------------------------------------
       SUBROUTINE TBES1D(TID, COLUMN, VALUE, NEXT, ACTVAL, STATUS)
C
C       SEARCH FOR ENTRY CLOSEST TO VALUE.
C       DOUBLE PRECISION VERSION
C
        IMPLICIT NONE
C
        INTEGER  TID
        INTEGER  COLUMN
        DOUBLE PRECISION VALUE
        INTEGER  NEXT
        DOUBLE PRECISION ACTVAL
        INTEGER  STATUS
C
        LOGICAL NULL, SELECT
        INTEGER NCOL, NROW, NSC, NAC, NAR, LEN, I, I1,TYPE
        DOUBLE PRECISION NEWVAL, DIST, DIST1
        CHARACTER*8   FORM
C
        INCLUDE  'MID_INCLUDE:TABLES.INC'
        INCLUDE  'MID_INCLUDE:TABLED.INC'
C
C ... CHECK ARGUMENTS
C
        CALL TBIGET(TID, NCOL, NROW, NSC, NAC, NAR, STATUS)
        IF (COLUMN.LT.0.OR.COLUMN.GT.NCOL) THEN
           STATUS = 1
           RETURN
        ENDIF
        CALL TBFGET(TID,COLUMN,FORM,LEN,TYPE,STATUS)
        IF (TYPE.EQ.D_C_FORMAT) THEN
           STATUS = 1
           RETURN
        ENDIF
C
C ... START SEARCHING 
C
        NEXT = 0
        I1    = 0
10      I1    = I1+1
        CALL TBSGET(TID, I1, SELECT, STATUS)
        IF (.NOT.SELECT) GOTO 10
        CALL TBERDD(TID, I1, COLUMN, NEWVAL, NULL, STATUS)
        IF (NULL.AND.I1.LT.NROW) GOTO 10
        NEXT   = I1
        ACTVAL = NEWVAL
        DIST   = DABS(ACTVAL-VALUE)
C
C ... ITERATION
C
        DO 20 I = I1, NROW
          CALL TBSGET(TID, I, SELECT, STATUS)
          IF (.NOT.SELECT) GOTO 20
          CALL TBERDD(TID, I, COLUMN, NEWVAL, NULL, STATUS)
          IF (.NOT. NULL) THEN
             DIST1 = DABS(NEWVAL-VALUE)
             IF (DIST1.LT.DIST) THEN
               NEXT   = I            
               DIST   = DIST1
               ACTVAL = NEWVAL
             ENDIF
          ENDIF
20      CONTINUE
       RETURN
       END

       SUBROUTINE TBES1I(TID, COLUMN, VALUE, NEXT, ACTVAL, STATUS)
C
C       SEARCH FOR ENTRY CLOSEST TO VALUE.
C       INTEGER VERSION
C
        IMPLICIT NONE
C
        INTEGER  TID
        INTEGER  COLUMN
        INTEGER  VALUE
        INTEGER  NEXT
        INTEGER  ACTVAL
        INTEGER  STATUS
C
        LOGICAL NULL, SELECT
        INTEGER NCOL, NROW, NSC, NAC, NAR, LEN, I, I1
        INTEGER NEWVAL, DIST, DIST1, TYPE
        CHARACTER*8   FORM
        INCLUDE  'MID_INCLUDE:TABLES.INC'
        INCLUDE  'MID_INCLUDE:TABLED.INC'
C
C ... CHECK ARGUMENTS
C
        CALL TBIGET(TID, NCOL, NROW, NSC, NAC, NAR, STATUS)
       IF (COLUMN.LT.0.OR.COLUMN.GT.NCOL) THEN
           STATUS = 1
           RETURN
       ENDIF
        CALL TBFGET(TID,COLUMN,FORM,LEN,TYPE,STATUS)
        IF (TYPE .EQ. D_C_FORMAT) THEN
           STATUS = 1
           RETURN
       ENDIF
C
C ... START SEARCHING 
C
        NEXT = 0
        I1    = 0
10      I1    = I1+1
        CALL TBSGET(TID, I1, SELECT, STATUS)
        IF (.NOT.SELECT) GOTO 10
        CALL TBERDI(TID, I1, COLUMN, NEWVAL, NULL, STATUS)
        IF (NULL.AND.I1.LT.NROW) GOTO 10
        NEXT   = I1
        ACTVAL = NEWVAL
        DIST   = IABS(ACTVAL-VALUE)
C
C ... ITERATION
C
        DO 20 I = I1, NROW
          CALL TBSGET(TID, I, SELECT, STATUS)
          IF (.NOT.SELECT) GOTO 20
          CALL TBERDI(TID, I, COLUMN, NEWVAL, NULL, STATUS)
          IF (.NOT. NULL) THEN
             DIST1 = IABS(NEWVAL-VALUE)
             IF (DIST1.LT.DIST) THEN
               NEXT   = I            
               DIST   = DIST1
               ACTVAL = NEWVAL
             ENDIF
          ENDIF
20      CONTINUE
       RETURN
       END

       SUBROUTINE TBES1R(TID, COLUMN, VALUE, NEXT, ACTVAL, STATUS)
C
C       SEARCH FOR ENTRY CLOSEST TO VALUE.
C       SINGLE PRECISION  VERSION
C
       IMPLICIT NONE
C
        INTEGER  TID
        INTEGER  COLUMN
        REAL     VALUE
        INTEGER  NEXT
        REAL     ACTVAL
        INTEGER  STATUS
C
        LOGICAL NULL, SELECT
        INTEGER TYPE
        INTEGER NCOL, NROW, NSC, NAC, NAR, LEN, I, I1
        REAL    NEWVAL, DIST, DIST1
        CHARACTER*8   FORM
        INCLUDE  'MID_INCLUDE:TABLES.INC'
        INCLUDE  'MID_INCLUDE:TABLED.INC'
C
C ... CHECK ARGUMENTS
C
        CALL TBIGET(TID, NCOL, NROW, NSC, NAC, NAR, STATUS)
       IF (COLUMN.LT.0.OR.COLUMN.GT.NCOL) THEN
           STATUS = 1
           RETURN
       ENDIF
        CALL TBFGET(TID,COLUMN,FORM,LEN,TYPE,STATUS)
        IF (TYPE .EQ. D_C_FORMAT) THEN
           STATUS = 1
           RETURN
       ENDIF
C
C ... START SEARCHING 
C
        NEXT  = 0
        I1    = 0
10      I1    = I1+1
        CALL TBSGET(TID, I1, SELECT, STATUS)
        IF (.NOT.SELECT) GOTO 10
        CALL TBERDR(TID, I1, COLUMN, NEWVAL, NULL, STATUS)
        IF (NULL.AND.I1.LT.NROW) GOTO 10
        NEXT   = I1
        ACTVAL = NEWVAL
        DIST   = ABS(ACTVAL-VALUE)
C
C ... ITERATION
C
        DO 20 I = I1, NROW
          CALL TBSGET(TID, I, SELECT, STATUS)
          IF (.NOT.SELECT) GOTO 20
          CALL TBERDR(TID, I, COLUMN, NEWVAL, NULL, STATUS)
          IF (.NOT. NULL) THEN
             DIST1 = ABS(NEWVAL-VALUE)
             IF (DIST1.LT.DIST) THEN
               NEXT   = I            
               DIST   = DIST1
               ACTVAL = NEWVAL
             ENDIF
          ENDIF
20      CONTINUE
       RETURN
       END

       SUBROUTINE TBES2D(TID,COLUMN1,COLUMN2,VALUE,
     .                       NEXT, ACTVAL, STATUS)
C
C       SEARCH FOR ENTRY CLOSEST TO VALUE
C       DOUBLE PRECISION VERSION
C
       IMPLICIT NONE
C
        INTEGER  TID
        INTEGER  COLUMN1
        INTEGER  COLUMN2
        DOUBLE PRECISION VALUE(2)
        INTEGER  NEXT
        DOUBLE PRECISION ACTVAL(2)
        INTEGER  STATUS
C
        LOGICAL NULL(2), SELECT
        INTEGER NCOL, NROW, NSC, NAC, NAR, LEN, I, I1, ICOL(2)
        INTEGER          TYPE
        DOUBLE PRECISION NEWVAL(2), DIST, DIST1
        CHARACTER*8      FORM
        INCLUDE  'MID_INCLUDE:TABLES.INC'
        INCLUDE  'MID_INCLUDE:TABLED.INC'
C
C ... CHECK ARGUMENTS
C
        CALL TBIGET(TID, NCOL, NROW, NSC, NAC, NAR, STATUS)
       IF (COLUMN1.LT.0.OR.COLUMN1.GT.NCOL.OR.
     .     COLUMN2.LT.0.OR.COLUMN2.GT.NCOL) THEN
           STATUS = 1
           RETURN
       ENDIF
        CALL TBFGET(TID,COLUMN1,FORM,LEN,TYPE,STATUS)
        IF (TYPE .EQ. D_C_FORMAT) THEN
           STATUS = 1
           RETURN
       ENDIF
        CALL TBFGET(TID,COLUMN2,FORM,LEN,TYPE,STATUS)
        IF (TYPE .EQ. D_C_FORMAT) THEN
           STATUS = 1
           RETURN
       ENDIF
C
C ... START SEARCHING 
C
        ICOL(1) = COLUMN1
        ICOL(2) = COLUMN2
        NEXT    = 0
        I1      = 0
10      I1      = I1+1
        CALL TBSGET(TID, I1, SELECT, STATUS)
        IF (.NOT.SELECT) GOTO 10
        CALL TBRRDD(TID, I1, 2, ICOL, NEWVAL, NULL, STATUS)
        IF ((NULL(1).OR.NULL(2)).AND.I1.LT.NROW) GOTO 10
        NEXT   = I1
        ACTVAL(1) = NEWVAL(1)
        ACTVAL(2) = NEWVAL(2)
        DIST      = DSQRT((ACTVAL(1)-VALUE(1))**2 + 
     .                    (ACTVAL(2)-VALUE(2))**2)  
C
C ... ITERATION
C
        DO 20 I = I1, NROW
          CALL TBSGET(TID, I, SELECT, STATUS)
          IF (.NOT.SELECT) GOTO 20
          CALL TBRRDD(TID, I, 2, ICOL, NEWVAL, NULL, STATUS)
          IF (.NOT. NULL(1) .AND. .NOT. NULL(2)) THEN
            DIST1     = DSQRT((NEWVAL(1)-VALUE(1))**2 + 
     .                        (NEWVAL(2)-VALUE(2))**2)  
             IF (DIST1.LT.DIST) THEN
               NEXT   = I            
               DIST   = DIST1
               ACTVAL(1) = NEWVAL(1)
               ACTVAL(2) = NEWVAL(2)
             ENDIF
          ENDIF
20      CONTINUE
       RETURN
       END

       SUBROUTINE TBES2I(TID,COLUMN1,COLUMN2,VALUE,
     .                       NEXT, ACTVAL, STATUS)
C
C       SEARCH FOR ENTRY CLOSEST TO VALUE
C       INTEGER  VERSION
C
       IMPLICIT NONE
C
        INTEGER  TID
        INTEGER  COLUMN1
        INTEGER  COLUMN2
        INTEGER  VALUE(2)
        INTEGER  NEXT
        INTEGER  ACTVAL(2)
        INTEGER  STATUS
C
        LOGICAL NULL(2), SELECT
        INTEGER NCOL, NROW, NSC, NAC, NAR, LEN, I, I1, ICOL(2)
        INTEGER NEWVAL(2), TYPE
        DOUBLE PRECISION DIST, DIST1
        CHARACTER*8   FORM
        INCLUDE  'MID_INCLUDE:TABLES.INC'
        INCLUDE  'MID_INCLUDE:TABLED.INC'
C
C ... CHECK ARGUMENTS
C
        CALL TBIGET(TID, NCOL, NROW, NSC, NAC, NAR, STATUS)
       IF (COLUMN1.LT.0.OR.COLUMN1.GT.NCOL.OR.
     .     COLUMN2.LT.0.OR.COLUMN2.GT.NCOL) THEN
           STATUS = 1
           RETURN
       ENDIF
        CALL TBFGET(TID,COLUMN1,FORM,LEN,TYPE,STATUS)
        IF (TYPE .EQ. D_C_FORMAT) THEN
           STATUS = 1
           RETURN
       ENDIF
        CALL TBFGET(TID,COLUMN2,FORM,LEN,TYPE,STATUS)
        IF (TYPE.EQ. D_C_FORMAT) THEN
           STATUS = 1
           RETURN
       ENDIF
C
C ... START SEARCHING 
C
        ICOL(1) = COLUMN1
        ICOL(2) = COLUMN2
        NEXT    = 0
        I1      = 0
10      I1      = I1+1
        CALL TBSGET(TID, I1, SELECT, STATUS)
        IF (.NOT.SELECT) GOTO 10
        CALL TBRRDI(TID, I1, 2, ICOL, NEWVAL, NULL, STATUS)
        IF ((NULL(1).OR.NULL(2)).AND.I1.LT.NROW) GOTO 10
        NEXT   = I1
        ACTVAL(1) = NEWVAL(1)
        ACTVAL(2) = NEWVAL(2)
        DIST1     = (ACTVAL(1)-VALUE(1))**2 + (ACTVAL(2)-VALUE(2))**2  
        DIST      = DSQRT(DIST1) 
C
C ... ITERATION
C
        DO 20 I = I1, NROW
          CALL TBSGET(TID, I, SELECT, STATUS)
          IF (.NOT.SELECT) GOTO 20
          CALL TBRRDI(TID, I, 2, ICOL, NEWVAL, NULL, STATUS)
          IF (.NOT. NULL(1) .AND. .NOT. NULL(2)) THEN
            DIST1 = (NEWVAL(1)-VALUE(1))**2 + (NEWVAL(2)-VALUE(2))**2  
            DIST1 = DSQRT(DIST1)
             IF (DIST1.LT.DIST) THEN
               NEXT   = I            
               DIST   = DIST1
               ACTVAL(1) = NEWVAL(1)
               ACTVAL(2) = NEWVAL(2)
             ENDIF
          ENDIF
20      CONTINUE
       RETURN
       END


       SUBROUTINE TBES2R(TID,COLUMN1,COLUMN2,VALUE,
     .                       NEXT, ACTVAL, STATUS)
C
C       SEARCH FOR ENTRY CLOSEST TO VALUE
C       SINGLE PRECISION VERSION
C
       IMPLICIT NONE
C
        INTEGER  TID
        INTEGER  COLUMN1
        INTEGER  COLUMN2
        REAL     VALUE(2)
        INTEGER  NEXT
        REAL     ACTVAL(2)
        INTEGER  STATUS
C
        LOGICAL NULL(2), SELECT
        INTEGER NCOL, NROW, NSC, NAC, NAR, LEN, I, I1, ICOL(2)
        INTEGER TYPE
        REAL    NEWVAL(2), DIST, DIST1
        CHARACTER*8   FORM
        INCLUDE  'MID_INCLUDE:TABLES.INC'
        INCLUDE  'MID_INCLUDE:TABLED.INC'
C
C ... CHECK ARGUMENTS
C
        CALL TBIGET(TID, NCOL, NROW, NSC, NAC, NAR, STATUS)
       IF (COLUMN1.LT.0.OR.COLUMN1.GT.NCOL.OR.
     .     COLUMN2.LT.0.OR.COLUMN2.GT.NCOL) THEN
           STATUS = 1
           RETURN
       ENDIF
        CALL TBFGET(TID,COLUMN1,FORM,LEN,TYPE,STATUS)
        IF (TYPE .EQ. D_C_FORMAT) THEN
           STATUS = 1
           RETURN
       ENDIF
        CALL TBFGET(TID,COLUMN2,FORM,LEN,TYPE,STATUS)
        IF (TYPE .EQ. D_C_FORMAT) THEN
           STATUS = 1
           RETURN
       ENDIF
C
C ... START SEARCHING 
C
        ICOL(1) = COLUMN1
        ICOL(2) = COLUMN2
        NEXT    = 0
        I1      = 0
10      I1      = I1+1
        CALL TBSGET(TID, I1, SELECT, STATUS)
        IF (.NOT.SELECT) GOTO 10
        CALL TBRRDR(TID, I1, 2, ICOL, NEWVAL, NULL, STATUS)
        IF ((NULL(1).OR.NULL(2)).AND.I1.LT.NROW) GOTO 10
        NEXT   = I1
        ACTVAL(1) = NEWVAL(1)
        ACTVAL(2) = NEWVAL(2)
        DIST      = SQRT((ACTVAL(1)-VALUE(1))**2 + 
     .                   (ACTVAL(2)-VALUE(2))**2)  
C
C ... ITERATION
C
        DO 20 I = I1, NROW
          CALL TBSGET(TID, I, SELECT, STATUS)
          IF (.NOT.SELECT) GOTO 20
          CALL TBRRDR(TID, I, 2, ICOL, NEWVAL, NULL, STATUS)
          IF (.NOT. NULL(1) .AND. .NOT. NULL(2)) THEN
            DIST1     = SQRT((NEWVAL(1)-VALUE(1))**2 + 
     .                       (NEWVAL(2)-VALUE(2))**2)  
             IF (DIST1.LT.DIST) THEN
               NEXT   = I            
               DIST   = DIST1
               ACTVAL(1) = NEWVAL(1)
               ACTVAL(2) = NEWVAL(2)
             ENDIF
          ENDIF
20      CONTINUE
       RETURN
       END

