home *** CD-ROM | disk | FTP | other *** search
- .pa
- STRING AND BUFFER MANIPULATION
-
- The purpose of these procedures is that FORTRAN is rather ill suited to string
- and buffer manipulation. Most of the operations can be done in FORTRAN but
- are extremely slow in comparison. Also there is the annoying practice of some
- compilers (e.g. HP's FTN7X) to use fixed length character variables. All of
- these routines were written in assembler.
-
-
- QUICK LIST OF STRING AND BUFFER MANIPULATION
-
- CSET..... set all the characters in a string
- DEC0DE... decode an array of reals contained in a character string
- FOLD..... case fold a character (a-z folds to A-Z)
- FOLDS.... case fold a character string (a-z folds to A-Z)
- IAND..... logical and
- IOR...... logical or
- IXOR..... logical exclusive or
- ILB...... left byte
- IRB...... right byte
- ISERCH... search for a character in a string
- MATCH.... check two character strings for a match
- MOVEC.... move one character string into another
- MOVEI.... move one integer array into another
- NBUFC1... determine the nominal length of a character string
- SWAPC.... swap two character strings
- SWAPI.... swap two integer arrays
- SORTC.... sort a group of character strings
- SORTCI... sort a group of indexed character strings
- SORTD.... sort an array of double precision reals
- SORTDI... sort an array of indexed double precision reals
- SORTI.... sort an array of integers
- SORTII... sort an array of indexed integers
- SORTR.... sort an array of reals
- SORTRI... sort an array of indexed reals
- .pa
- NAME: CSET
- PURPOSE: set all the characters in a string equal to a specific
- character (such as blanks)
- TYPE: subroutine (far external)
- SYNTAX: CALL CSET(CBUF,NBUF,' ')
- INPUT: a CHARACTER*1 variable (here ' ')
- NBUF (INTEGER*2) number of characters in the target string
- OUTPUT: CBUF (CHARACTER*1 CBUF(NBUF) or CHARACTER*80 CBUF, NBUF=80)
-
-
- NAME: DEC0DE (note the "0" (zero), do not use an "O" (oh))
- PURPOSE: decode an array of reals contained in a character string
- TYPE: subroutine (far external)
- SYNTAX: CALL DEC0DE(CBUF,NBUF,NCOL,R,N,IER)
- INPUT: CBUF (any character string like '123 34.E4 5*0 100')
- NBUF (INTEGER*2) the number of characters in CBUF
- N (INTEGER*2) number of elements in R
- NOTE: if you set N to a negative number, then DEC0DE will return in its
- place the +number of reals actually decoded (of course, don't
- use a constant like "-3" for this!)
- OUTPUT: NCOL (INTEGER*2) the column where decoding stopped
- R (REAL*4) an array (may be only 1 element)
- IER (INTEGER*2) error return indicator (IER=0 is normal)
- USE: In case you haven't noticed, some misguided persons at DEC and
- Microsoft forgot to include the capability of free-format
- reads from a character string (some people call character
- strings "internal files" - why, is a mystery to me). Of
- course, this is the most OBVIOUS reason for reading something
- from a character string... perhaps that's why they left it
- out. Well, DEC0DE is just the fix.
-
- DEC0DE will return an error if the syntax is incorrect or if
- the string is empty. You must have at least one number in the
- string. Missing numbers at the trailing end of a string will
- be set to zero (viz. if you try to read 6 numbers and there
- are only 3, the last 3 will come back as zero).
-
- Some examples of free format reals are given below. Note that
- you can use the "*" to repeat numbers. Commas are optional.
-
- 100 1.234 .0000123,45E4, 3*53.123 5*-7 -12.345E-05
-
- DEC0DE is written in assembler and is actually faster than
- Microsoft's or HP's equivalent. HP's FORTRAN will actually
- perform this operation.
-
- When I want to read integers from a character string I first
- read reals, then apply the "NINT" function as below
-
- CALL DEC0DE(CBUF,6,NCOL,R,1,IER)
- IF(IER.NE.0) GO TO 999
- I=NINT(R)
-
- The NINT function performs the real>integer conversion that is
- what you probably want: (nearest integer) rather than the INT
- function (truncate to integer).
-
-
- NAME: FOLD
- PURPOSE: case fold a character (a-z folds to A-Z)
- TYPE: CHARACTER*1 function (far external)
- SYNTAX: C2=FOLD(C1)
- INPUT: C1 (CHARACTER*1)
- OUTPUT: C2 (CHARACTER*1)
-
-
- NAME: FOLDS
- PURPOSE: case fold a character string (a-z folds to A-Z)
- TYPE: subroutine (far external)
- SYNTAX: CALL FOLDS(CBUF,NBUF)
- INPUT: CBUF (CHARACTER*1 CBUF(NBUF) or CHARACTER*80 CBUF, NBUF=80)
- NBUF (INTEGER*2) number of characters in the string
- OUTPUT: CBUF
-
-
- NAME: ISERCH
- PURPOSE: search for a character in a string
- TYPE: INTEGER*2 function (far external)
- SYNTAX: K=ISERCH('?','are you kidding?',NBUF)
- INPUT: a CHARACTER*1 variable (here '?')
- CBUF (CHARACTER*1 CBUF(NBUF) or CHARACTER*80 CBUF, NBUF=80)
- NBUF (INTEGER*2) number of characters in the string
- OUTPUT: K (INTEGER*2)
- NOTE: 0<=K<=NBUF (if found, I will be first occurrence, if not
- found, K=0)
-
-
- NAME: IAND/IOR/IXOR
- PURPOSE: logical functions
- TYPE: INTEGER*2 function (far external)
- SYNTAX: I=IAND(J,K) I=IOR(J,K) I=IXOR(J,K)
- INPUT: J,K INTEGER*2 variables
- OUTPUT: I (INTEGER*2)
-
-
- NAME: ILB/IRB
- PURPOSE: integer>integer/character
- TYPE: INTEGER*2 function (far external)
- SYNTAX: I=ILB(J) I=IRB(J)
- INPUT: J INTEGER*2 character
- OUTPUT: I (INTEGER*2)
- NOTE: I=ILB(J) is the same as I=J/256
- I=IRB(J) is the same as I=MOD(J,256)
-
-
- NAME: MATCH
- PURPOSE: check two character strings for a match
- TYPE: LOGICAL*2 function (far external)
- SYNTAX: IF(MATCH(CBUF,'STOP',4)) GO TO 999
- INPUT: two character strings (may be CHARACTER*1 CBUF1(NBUF),
- CBUF2(NBUF) or CHARACTER*4 CBUF1,CBUF2)
- NBUF (INTEGER*2) number of characters in the strings
- OUTPUT: .true./.false.
- NOTE: the strings need not have the same length as long as they are
- both at least NBUF in length (here NBUF=4)
-
- One annoying thing about FORTRAN is that it won't compare the
- first 4 characters of a string read in as 4A1 with a string
- of length 4 like 'STOP'. MATCH solves this problem.
-
-
- NAME: MOVEC
- PURPOSE: move one character string into another
- TYPE: subroutine (far external)
- SYNTAX: CALL MOVEC(CBUF1,CBUF2,NBUF) or CALL MOVEC(CBUF,'STOP',4)
- INPUT: CBUF2 a character string (may be CHARACTER*1 CBUF2(NBUF) or
- CHARACTER*4 CBUF2)
- NBUF (INTEGER*2) number of characters in the strings
- OUTPUT: CBUF1 a character string (may be CHARACTER*1 CBUF1(NBUF) or
- CHARACTER*4 CBUF1)
- NOTE: the strings need not have the same length as long as they are
- both at least NBUF in length (here NBUF=4)
-
- One annoying thing about FORTRAN is that it won't equivalence
- first 4 characters of a 4A1 string to a string of length 4
- like 'STOP'. MOVEC solves this problem. It's also much faster.
-
-
- NAME: MOVEI
- PURPOSE: move one integer array into another
- TYPE: subroutine (far external)
- SYNTAX: CALL MOVEI(IBUF1,IBUF2,NBUF)
- INPUT: IBUF2 (INTEGER*2) an array
- NBUF (INTEGER*2) number of elements in the arrays
- OUTPUT: IBUF1 (INTEGER*2) an array
- NOTE: the strings need not have the same length as long as they are
- both at least NBUF in length
-
- This is about seventeen times as fast as a FORTRAN "DO LOOP".
-
-
- NAME: NBUFC1
- PURPOSE: determine the nominal length of a character string excluding
- trailing blanks
- TYPE: INTEGER*2 function (far external)
- SYNTAX: IF(NBUFC1(CBUF,80).EQ.0) STOP or
- L=NBUFC1(CBUF,NBUF)
- INPUT: CBUF a character string (may be CHARACTER*1 CBUF(NBUF) or
- CHARACTER*4 CBUF)
- NBUF (INTEGER*2) total number of characters in the string
- OUTPUT: L (INTEGER*2) nominal length of string
-
-
- NAME: SWAPC
- PURPOSE: swap two character strings
- TYPE: subroutine (far external)
- SYNTAX: CALL SWAPC(CBUF1,CBUF2,NBUF)
- INPUT: CBUF1 and CBUF2 character strings (may be CHARACTER*1
- CBUF1(NBUF),CBUF2(NBUF) or CHARACTER*4 CBUF1,CBUF2)
- NBUF (INTEGER*2) number of characters in the strings
- OUTPUT: CBUF1,CBUF2
- NOTE: the strings need not have the same length as long as they are
- both at least NBUF in length
-
-
- NAME: SWAPI
- PURPOSE: swap two integer arrays
- TYPE: subroutine (far external)
- SYNTAX: CALL SWAPI(IBUF1,IBUF2,NBUF)
- INPUT: IBUF1,IBUF2 (INTEGER*2) an arrays
- NBUF (INTEGER*2) number of elements in the arrays
- OUTPUT: IBUF1,IBUF2
- NOTE: the arrays need not have the same length as long as they are
- both at least NBUF in length
-
-
- NAME: SORTC
- PURPOSE: sort a group of character strings
- TYPE: subroutine (far external)
- SYNTAX: CALL SORTC(GROUP,L,N,ASCEND)
- INPUT: GROUP a group of character strings (may be CHARACTER*1
- GROUP(L,N) or CHARACTER*64 GROUP(N) if L=64)
- L (INTEGER*2) length of the strings
- N (INTEGER*2) number of strings in group
- ASCEND (LOGICAL*2) .true. for ascending order, .false. for
- descending order
- OUTPUT: GROUP
- NOTE: A modification of the shell sort is used.
-
- This operation isn't even possible in FORTRAN because you
- can't pass the length of a character variable as a formal
- parameter.
-
- WARNING: Be careful that GROUP does not cross a segment boundary!
- That is, GROUP can not contain more than 65356 bytes nor
- be part of a data group that spans a segment boundary. See
- the comments in the section on vector emulation for more
- details on segment boundaries.
-
-
- NAME: SORTCI
- PURPOSE: sort a group of indexed character strings
- TYPE: subroutine (far external)
- SYNTAX: CALL SORTCI(GROUP,L,INDEX,N,ASCEND)
- INPUT: GROUP a group of character strings (may be CHARACTER*1
- GROUP(L,N) or CHARACTER*64 GROUP(N) if L=64)
- L (INTEGER*2) length of the strings
- INDEX (INTEGER*2) some index like 1,2,3,4,5...
- N (INTEGER*2) number of strings in group
- ASCEND (LOGICAL*2) .true. for ascending order, .false. for
- descending order
- OUTPUT: GROUP, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
- upon return from SORTCI you can tell what the change was from
- the original order - INDEX will come back as something like
- 13,2,35,27,3,18,...)
- NOTE: A modification of the shell sort is used.
-
- This operation isn't even possible in FORTRAN because you
- can't pass the length of a character variable as a formal
- parameter.
-
- WARNING: Be careful that GROUP and INDEX do not cross segment
- boundaries. That is, GROUP can not contain more than 65356
- bytes and INDEX can not contain mode than 32768 elements nor
- be part of a data group that spans a segment boundary. See
- the comments in the section on vector emulation for more
- details on segment boundaries.
-
-
- NAME: SORTD
- PURPOSE: sort an array of double precision reals
- TYPE: subroutine (far external)
- SYNTAX: CALL SORTD(D,N,ASCEND)
- INPUT: D (REAL*8) array
- N (INTEGER*2) number of elements in D
- ASCEND (LOGICAL*2) .true. for ascending order, .false. for
- descending order
- OUTPUT: D
- NOTE: A modification of the shell sort is used.
-
- WARNING: Be careful that D does not cross a segment boundary!
- That is, D can not contain more than 8192 elements nor
- be part of a data group that spans a segment boundary. See
- the comments in the section on vector emulation for more
- details on segment boundaries.
-
-
- NAME: SORTDI
- PURPOSE: sort an array of indexed double precision reals
- TYPE: subroutine (far external)
- SYNTAX: CALL SORTDI(D,INDEX,N,ASCEND)
- INPUT: D (REAL*8) array
- INDEX (INTEGER*2) some index like 1,2,3,4,5...
- N (INTEGER*2) number of elements in D
- ASCEND (LOGICAL*2) .true. for ascending order, .false. for
- descending order
- OUTPUT: D, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
- upon return from SORTDI you can tell what the change was from
- the original order - INDEX will come back as something like
- 13,2,35,27,3,18,...)
- NOTE: A modification of the shell sort is used.
-
- WARNING: Be careful that D and INDEX do not cross segment
- boundaries. That is, D can not contain more than 8192
- bytes and INDEX can not contain mode than 32766 elements nor
- be part of a data group that spans a segment boundary. See
- the comments in the section on vector emulation for more
- details on segment boundaries.
-
-
- NAME: SORTI
- PURPOSE: sort an array of integers
- TYPE: subroutine (far external)
- SYNTAX: CALL SORTI(K,N,ASCEND)
- INPUT: K (INTEGER*2) array
- N (INTEGER*2) number of elements in K
- ASCEND (LOGICAL*2) .true. for ascending order, .false. for
- descending order
- OUTPUT: K
- NOTE: A modification of the shell sort is used.
-
- WARNING: Be careful that K does not cross a segment boundary!
- That is, K can not contain more than 32768 elements nor
- be part of a data group that spans a segment boundary. See
- the comments in the section on vector emulation for more
- details on segment boundaries.
-
-
- NAME: SORTII
- PURPOSE: sort an array of indexed integers
- TYPE: subroutine (far external)
- SYNTAX: CALL SORTII(K,INDEX,N,ASCEND)
- INPUT: K (INTEGER*2) array
- INDEX (INTEGER*2) some index like 1,2,3,4,5...
- N (INTEGER*2) number of elements in K
- ASCEND (LOGICAL*2) .true. for ascending order, .false. for
- descending order
- OUTPUT: K, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
- upon return from SORTII you can tell what the change was from
- the original order - INDEX will come back as something like
- 13,2,35,27,3,18,...)
- NOTE: A modification of the shell sort is used.
-
- WARNING: Be careful that K and INDEX do not cross segment
- boundaries. That is, K can not contain more than 32768
- bytes and INDEX can not contain mode than 32766 elements nor
- be part of a data group that spans a segment boundary. See
- the comments in the section on vector emulation for more
- details on segment boundaries.
-
-
- NAME: SORTR
- PURPOSE: sort an array of reals
- TYPE: subroutine (far external)
- SYNTAX: CALL SORTR(R,N,ASCEND)
- INPUT: R (REAL*4) array
- N (INTEGER*2) number of elements in R
- ASCEND (LOGICAL*2) .true. for ascending order, .false. for
- descending order
- OUTPUT: R
- NOTE: A modification of the shell sort is used.
-
- WARNING: Be careful that R does not cross a segment boundary!
- That is, R can not contain more than 16384 elements nor
- be part of a data group that spans a segment boundary. See
- the comments in the section on vector emulation for more
- details on segment boundaries.
-
-
- NAME: SORTRI
- PURPOSE: sort an array of indexed reals
- TYPE: subroutine (far external)
- SYNTAX: CALL SORTRI(R,INDEX,N,ASCEND)
- INPUT: R (REAL*4) array
- INDEX (INTEGER*2) some index like 1,2,3,4,5...
- N (INTEGER*2) number of elements in R
- ASCEND (LOGICAL*2) .true. for ascending order, .false. for
- descending order
- OUTPUT: R, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
- upon return from SORTRI you can tell what the change was from
- the original order - INDEX will come back as something like
- 13,2,35,27,3,18,...)
- NOTE: A modification of the shell sort is used.
-
- WARNING: Be careful that R and INDEX do not cross segment
- boundaries. That is, R can not contain more than 16384
- bytes and INDEX can not contain mode than 32766 elements nor
- be part of a data group that spans a segment boundary. See
- the comments in the section on vector emulation for more
- details on segment boundaries.