123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112 |
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !-----------------------------------------------------------------------
- ! CVS m_List.F90,v 1.36 2007-11-06 00:03:31 jacob Exp
- ! CVS MCT_2_8_0
- !BOP -------------------------------------------------------------------
- !
- ! !MODULE: m_List - A List Manager
- !
- ! !DESCRIPTION: A {\em List} is a character buffer comprising
- ! substrings called {\em items} separated by colons, combined with
- ! indexing information describing (1) the starting point in the character
- ! buffer of each substring, and (2) the length of each substring. The
- ! only constraints on the valid list items are (1) the value of an
- ! item does not contain the ``\verb":"'' delimitter, and (2) leading
- ! and trailing blanks are stripped from any character string presented
- ! to define a list item (although any imbeded blanks are retained).
- !
- ! {\bf Example:} Suppose we wish to define a List containing the
- ! items {\tt 'latitude'}, {\tt 'longitude'}, and {\tt 'pressure'}.
- ! The character buffer of the List containing these items will be the
- ! 27-character string
- ! \begin{verbatim}
- ! 'latitude:longitude:pressure'
- ! \end{verbatim}
- ! and the indexing information is summarized in the table below.
- !
- !\begin{table}[htbp]
- !\begin{center}
- !\begin{tabular}{|c|c|c|}
- !\hline
- !{\bf Item} & {\bf Starting Point in Buffer} & {\bf Length} \\
- !\hline
- !{\tt latitude} & 1 & 8 \\
- !\hline
- !{\tt longitude} & 9 & 9 \\
- !\hline
- !{\tt pressure} & 20 & 8\\
- !\hline
- !\end{tabular}
- !\end{center}
- !\end{table}
- !
- ! One final note: All operations for the {\tt List} datatype are
- ! {\bf case sensitive}.
- !
- ! !INTERFACE:
- module m_List
- ! !USES:
- !
- ! No other Fortran modules are used.
- implicit none
- private ! except
- ! !PUBLIC TYPES:
- public :: List ! The class data structure
- Type List
- #ifdef SEQUENCE
- sequence
- #endif
- character(len=1),dimension(:),pointer :: bf
- integer, dimension(:,:),pointer :: lc
- End Type List
- ! !PUBLIC MEMBER FUNCTIONS:
- public :: init
- public :: clean
- public :: nullify
- public :: index
- public :: get_indices
- public :: test_indices
- public :: nitem
- public :: get
- public :: identical
- public :: assignment(=)
- public :: allocated
- public :: copy
- public :: exportToChar
- public :: exportToString
- public :: CharBufferSize
- public :: append
- public :: concatenate
- public :: bcast
- public :: send
- public :: recv
- public :: GetSharedListIndices
- interface init ; module procedure &
- init_, &
- initStr_, &
- initstr1_
- end interface
- interface clean; module procedure clean_; end interface
- interface nullify; module procedure nullify_; end interface
- interface index; module procedure &
- index_, &
- indexStr_
- end interface
- interface get_indices; module procedure get_indices_; end interface
- interface test_indices; module procedure test_indices_; end interface
- interface nitem; module procedure nitem_; end interface
- interface get ; module procedure &
- get_, &
- getall_, &
- getrange_
- end interface
- interface identical; module procedure identical_; end interface
- interface assignment(=)
- module procedure copy_
- end interface
- interface allocated ; module procedure &
- allocated_
- end interface
- interface copy ; module procedure copy_ ; end interface
- interface exportToChar ; module procedure &
- exportToChar_
- end interface
- interface exportToString ; module procedure &
- exportToString_
- end interface
- interface CharBufferSize ; module procedure &
- CharBufferSize_
- end interface
- interface append ; module procedure append_ ; end interface
- interface concatenate ; module procedure concatenate_ ; end interface
- interface bcast; module procedure bcast_; end interface
- interface send; module procedure send_; end interface
- interface recv; module procedure recv_; end interface
- interface GetSharedListIndices; module procedure &
- GetSharedListIndices_
- end interface
- ! !REVISION HISTORY:
- ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- ! 16May01 - J. Larson <larson@mcs.anl.gov> - Several changes / fixes:
- ! public interface for copy_(), corrected version of copy_(),
- ! corrected version of bcast_().
- ! 15Oct01 - J. Larson <larson@mcs.anl.gov> - Added the LOGICAL
- ! function identical_().
- ! 14Dec01 - J. Larson <larson@mcs.anl.gov> - Added the LOGICAL
- ! function allocated_().
- ! 13Feb02 - J. Larson <larson@mcs.anl.gov> - Added the List query
- ! functions exportToChar() and CharBufferLength().
- ! 13Jun02- R.L. Jacob <jacob@mcs.anl.gov> - Move GetSharedListIndices
- ! from mct to this module.
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname='MCT(MPEU)::m_List'
- contains
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: init_ - Initialize a List from a CHARACTER String
- !
- ! !DESCRIPTION:
- !
- ! A list is a string in the form of ``\verb"Larry:Moe:Curly"'',
- ! or ``\verb"lat:lon:lev"'', combined with substring location and
- ! length information. Through the initialization call, the
- ! items delimited by ``\verb":"'' are stored as an array of sub-
- ! strings of a long string, accessible through an array of substring
- ! indices. The only constraints now on the valid list entries are,
- ! (1) the value of an entry does not contain ``\verb":"'', and (2)
- ! The leading and the trailing blanks are insignificant, although
- ! any imbeded blanks are. For example,
- !
- ! \begin{verbatim}
- ! call init_(aList, 'batman :SUPERMAN:Green Lantern: Aquaman')
- ! \end{verbatim}
- ! will result in {\tt aList} having four items: 'batman', 'SUPERMAN',
- ! 'Green Lantern', and 'Aquaman'. That is
- ! \begin{verbatim}
- ! aList%bf = 'batman:SUPERMAN:Green Lantern:Aquaman'
- ! \end{verbatim}
- !
- ! !INTERFACE:
- subroutine init_(aList,Values)
- ! !USES:
- !
- use m_die,only : die
- use m_mall,only : mall_mci,mall_ison
-
- implicit none
- ! !INPUT PARAMETERS:
- !
- character(len=*),intent(in) :: Values ! ":" delimited names
- ! !OUTPUT PARAMETERS:
- !
- type(List),intent(out) :: aList ! an indexed string values
-
- ! !REVISION HISTORY:
- ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::init_'
- character(len=1) :: c
- integer :: ib,ie,id,lb,le,ni,i,ier
- ! Pass 1, getting the sizes
- le=0
- ni=0
- ib=1
- ie=0
- id=0
- do i=1,len(Values)
- c=Values(i:i)
- select case(c)
- case(' ')
- if(ib==i) ib=i+1 ! moving ib up, starting from the next
- case(':')
- if(ib<=ie) then
- ni=ni+1
- id=1 ! mark a ':'
- endif
- ib=i+1 ! moving ib up, starting from the next
- case default
- ie=i
- if(id==1) then ! count an earlier marked ':'
- id=0
- le=le+1
- endif
- le=le+1
- end select
- end do
- if(ib<=ie) ni=ni+1
- ! COMPILER MAY NOT SIGNAL AN ERROR IF
- ! ALIST HAS ALREADY BEEN INITIALIZED.
- ! PLEASE CHECK FOR PREVIOUS INITIALIZATION
-
- allocate(aList%bf(le),aList%lc(0:1,ni),stat=ier)
- if(ier /= 0) call die(myname_,'allocate()',ier)
- if(mall_ison()) then
- call mall_mci(aList%bf,myname)
- call mall_mci(aList%lc,myname)
- endif
- ! Pass 2, copy the value and assign the pointers
- lb=1
- le=0
- ni=0
- ib=1
- ie=0
- id=0
- do i=1,len(Values)
- c=Values(i:i)
- select case(c)
- case(' ')
- if(ib==i) ib=i+1 ! moving ib up, starting from the next
- case(':')
- if(ib<=ie) then
- ni=ni+1
- aList%lc(0:1,ni)=(/lb,le/)
- id=1 ! mark a ':'
- endif
- ib=i+1 ! moving ib up, starting from the next
- lb=le+2 ! skip to the next non-':' and non-','
- case default
- ie=i
- if(id==1) then ! copy an earlier marked ':'
- id=0
- le=le+1
- aList%bf(le)=':'
- endif
- le=le+1
- aList%bf(le)=c
- end select
- end do
- if(ib<=ie) then
- ni=ni+1
- aList%lc(0:1,ni)=(/lb,le/)
- endif
- end subroutine init_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: initStr_ - Initialize a List Using the String Type
- !
- ! !DESCRIPTION: This routine initializes a {\tt List} datatype given
- ! an input {\tt String} datatype (see {\tt m\_String} for more
- ! information regarding the {\tt String} type). The contents of the
- ! input {\tt String} argument {\tt pstr} must adhere to the restrictions
- ! stated for character input stated in the prologue of the routine
- ! {\tt init\_()} in this module.
- !
- ! !INTERFACE:
- subroutine initStr_(aList, pstr)
- ! !USES:
- !
- use m_String, only : String,toChar
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(String),intent(in) :: pstr
- ! !OUTPUT PARAMETERS:
- !
- type(List),intent(out) :: aList ! an indexed string values
- ! !REVISION HISTORY:
- ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::initStr_'
- call init_(aList,toChar(pstr))
- end subroutine initStr_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: initStr1_ - Initialize a List Using an Array of Strings
- !
- ! !DESCRIPTION: This routine initializes a {\tt List} datatype given
- ! as input array of {\tt String} datatypes (see {\tt m\_String} for more
- ! information regarding the {\tt String} type). The contents of each
- ! {\tt String} element of the input array {\tt strs} must adhere to the
- ! restrictions stated for character input stated in the prologue of the
- ! routine {\tt init\_()} in this module. Specifically, no element in
- ! {\tt strs} may contain the colon \verb':' delimiter, and any
- ! leading or trailing blanks will be stripped (though embedded blank
- ! spaces will be retained). For example, consider an invocation of
- ! {\tt initStr1\_()} where the array {\tt strs(:)} contains four entries:
- ! {\tt strs(1)='John'}, {\tt strs(2)=' Paul'},
- ! {\tt strs(3)='George '}, and {\tt strs(4)=' Ringo'}. The resulting
- ! {\tt List} output {\tt aList} will have
- ! \begin{verbatim}
- ! aList%bf = 'John:Paul:George:Ringo'
- ! \end{verbatim}
- ! !INTERFACE:
- subroutine initStr1_(aList, strs)
- ! !USES:
- !
- use m_String, only : String,toChar
- use m_String, only : len
- use m_String, only : ptr_chars
- use m_die,only : die
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(String),dimension(:),intent(in) :: strs
- ! !OUTPUT PARAMETERS:
- !
- type(List),intent(out) :: aList ! an indexed string values
- ! !REVISION HISTORY:
- ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::initStr1_'
- character(len=1),allocatable,dimension(:) :: ch1
- integer :: ier
- integer :: n,i,lc,le
- n=size(strs)
- le=0
- do i=1,n
- le=le+len(strs(i))
- end do
- le=le+n-1 ! for n-1 ":"s
- allocate(ch1(le),stat=ier)
- if(ier/=0) call die(myname_,'allocate()',ier)
- le=0
- do i=1,n
- if(i>1) then
- le=le+1
- ch1(le)=':'
- endif
- lc=le+1
- le=le+len(strs(i))
- ch1(lc:le)=ptr_chars(strs(i))
- end do
-
- call init_(aList,toChar(ch1))
- deallocate(ch1,stat=ier)
- if(ier/=0) call die(myname_,'deallocate()',ier)
- end subroutine initStr1_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: clean_ - Deallocate Memory Used by a List
- !
- ! !DESCRIPTION: This routine deallocates the allocated memory components
- ! of the input/output {\tt List} argument {\tt aList}. Specifically, it
- ! deallocates {\tt aList\%bf} and {\tt aList\%lc}. If the optional
- ! output {\tt INTEGER} arguemnt {\tt stat} is supplied, no warning will
- ! be printed if the Fortran intrinsic {\tt deallocate()} returns with an
- ! error condition.
- !
- ! !INTERFACE:
- subroutine clean_(aList, stat)
- ! !USES:
- !
- use m_die, only : warn
- use m_mall, only : mall_mco,mall_ison
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- !
- type(List), intent(inout) :: aList
- ! !OUTPUT PARAMETERS:
- !
- integer, optional, intent(out) :: stat
- ! !REVISION HISTORY:
- ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- ! 1Mar02 - E.T. Ong <eong@mcs.anl.gov> - added stat argument and
- ! removed die to prevent crashes.
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::clean_'
- integer :: ier
- if(mall_ison()) then
- if(associated(aList%bf)) call mall_mco(aList%bf,myname_)
- if(associated(aList%lc)) call mall_mco(aList%lc,myname_)
- endif
- if(associated(aList%bf) .and. associated(aList%lc)) then
- deallocate(aList%bf, aList%lc, stat=ier)
- if(present(stat)) then
- stat=ier
- else
- if(ier /= 0) call warn(myname_,'deallocate(aList%...)',ier)
- endif
- endif
- end subroutine clean_
- !--- -------------------------------------------------------------------
- ! Math + Computer Science Division / Argonne National Laboratory !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: nullify_ - Nullify Pointers in a List
- !
- ! !DESCRIPTION: In Fortran 90, pointers may have three states:
- ! (1) {\tt ASSOCIATED}, that is the pointer is pointing at a target,
- ! (2) {\tt UNASSOCIATED}, and (3) {\tt UNINITIALIZED}. On some
- ! platforms, the Fortran intrinsic function {\tt associated()}
- ! will view uninitialized pointers as {\tt UNASSOCIATED} by default.
- ! This is not always the case. It is good programming practice to
- ! nullify pointers if they are not to be used. This routine nullifies
- ! the pointers present in the {\tt List} datatype.
- !
- ! !INTERFACE:
- subroutine nullify_(aList)
- ! !USES:
- !
- use m_die,only : die
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- !
- type(List),intent(inout) :: aList
- ! !REVISION HISTORY:
- ! 18Jun01 - J.W. Larson - <larson@mcs.anl.gov> - initial version
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::nullify_'
- nullify(aList%bf)
- nullify(aList%lc)
- end subroutine nullify_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: nitem_ - Return the Number of Items in a List
- !
- ! !DESCRIPTION:
- ! This function enumerates the number of items in the input {\tt List}
- ! argument {\tt aList}. For example, suppose
- ! \begin{verbatim}
- ! aList%bf = 'John:Paul:George:Ringo'
- ! \end{verbatim}
- ! Then,
- ! $${\tt nitem\_(aList)} = 4 .$$
- !
- ! !INTERFACE:
- integer function nitem_(aList)
- ! !USES:
- !
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List),intent(in) :: aList
- ! !REVISION HISTORY:
- ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- ! 10Oct01 - J.W. Larson <larson@mcs.anl.gov> - modified routine to
- ! check pointers aList%bf and aList%lc using the f90
- ! intrinsic ASSOCIATED before proceeding with the item
- ! count. If these pointers are UNASSOCIATED, an item
- ! count of zero is returned.
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::nitem_'
- integer :: NumItems
- ! Initialize item count to zero
- NumItems = 0
- ! If the List pointers are ASSOCIATED, perform item count:
- if(ASSOCIATED(aList%bf) .and. ASSOCIATED(aList%lc)) then
- NumItems = size(aList%lc,2)
- endif
- nitem_ = NumItems
- end function nitem_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: index_ - Return Rank in a List of a Given Item (CHARACTER)
- !
- ! !DESCRIPTION:
- ! This function returns the rank of an item (defined by the
- ! {\tt CHARACTER} argument {\tt item}) in the input {\tt List} argument
- ! {\tt aList}. If {\tt item} is not present in {\tt aList}, then zero
- ! is returned. For example, suppose
- ! \begin{verbatim}
- ! aList%bf = 'Bob:Carol:Ted:Alice'
- ! \end{verbatim}
- ! Then, ${\tt index\_(aList, 'Ted')}=3$, ${\tt index\_(aList, 'Carol')}=2$,
- ! and ${\tt index\_(aList, 'The Dude')}=0.$
- !
- ! !INTERFACE:
- integer function index_(aList, item)
- ! !USES:
- !
- use m_String, only : toChar
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: aList ! a List of names
- character(len=*),intent(in) :: item ! a given item name
- ! !REVISION HISTORY:
- ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::index_'
- integer :: i,lb,le
- integer :: itemLength, length, nMatch, j
- ! How long is the input item name?
- itemLength = len(item)
- ! Set output to zero (no item match) value:
- index_=0
- ! Now, go through the aList one item at a time
- ITEM_COMPARE: do i=1,size(aList%lc,2) ! == nitem_(aList)
- ! Compute some stats for the current item in aList:
- lb=aList%lc(0,i) ! starting index of item in aList%bf
- le=aList%lc(1,i) ! ending index item in aList%bf
- length = le -lb + 1 ! length of the current item
- if(length /= itemLength) then ! this list item can't match input item
- CYCLE ! that is, jump to the next item in aList...
- else ! compare one character at a time...
- ! Initialize number of matching characters in the two strings
- nMatch = 0
- ! Now, compare item to the current item in aList one character
- ! at a time:
- CHAR_COMPARE: do j=1,length
- if(aList%bf(lb+j-1) == item(j:j)) then ! a match for this character
- nMatch = nMatch + 1
- else
- EXIT
- endif
- end do CHAR_COMPARE
- ! Check the number of leading characters in the current item in aList
- ! that match the input item. If it is equal to the item length, then
- ! we have found a match and are finished. Otherwise, we cycle on to
- ! the next item in aList.
- if(nMatch == itemLength) then
- index_ = i
- EXIT
- endif
- ! Old code that does not work with V. of the IBM
- ! if(item==toChar(aList%bf(lb:le))) then
- ! index_=i
- ! exit
- endif
- end do ITEM_COMPARE
- end function index_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: indexStr_ - Return Rank in a List of a Given Item (String)
- !
- ! !DESCRIPTION:
- ! This function performs the same operation as the function
- ! {\tt index\_()}, but the item to be indexed is instead presented in
- ! the form of a {\tt String} datatype (see the module {\tt m\_String}
- ! for more information about the {\tt String} type). This routine
- ! searches through the input {\tt List} argument {\tt aList} for an
- ! item that matches the item defined by {\tt itemStr}, and if a match
- ! is found, the rank of the item in the list is returned (see also the
- ! prologue for the routine {\tt index\_()} in this module). If no match
- ! is found, a value of zero is returned.
- !
- ! !INTERFACE:
- integer function indexStr_(aList, itemStr)
- ! !USES:
- !
- use m_String,only : String,toChar
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: aList ! a List of names
- type(String), intent(in) :: itemStr
- ! !REVISION HISTORY:
- ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- ! 25Oct02 - R. Jacob <jacob@mcs.anl.gov> - just call index_ above
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::indexStr_'
- indexStr_=0
- indexStr_=index_(aList,toChar(itemStr))
- end function indexStr_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: allocated_ - Check Pointers in a List for Association Status
- !
- ! !DESCRIPTION:
- ! This function checks the input {\tt List} argument {\tt inList} to
- ! determine whether or not it has been allocated. It does this by
- ! invoking the Fortran90 intrinsic function {\tt associated()} on the
- ! pointers {\tt inList\%bf} and {\tt inList\%lc}. If both of these
- ! pointers are associated, the return value is {\tt .TRUE.}.
- !
- ! {\bf N.B.:} In Fortran90, pointers have three different states:
- ! {\tt ASSOCIATED}, {\tt UNASSOCIATED}, and {\tt UNDEFINED}.
- ! If a pointer is {\tt UNDEFINED}, this function may return either
- ! {\tt .TRUE.} or {\tt .FALSE.} values, depending on the Fortran90
- ! compiler. To avoid such problems, we advise that users invoke the
- ! {\tt List} method {\tt nullify()} to nullify any {\tt List} pointers
- ! for {\tt List} variables that are not initialized.
- !
- ! !INTERFACE:
- logical function allocated_(inList)
- ! !USES:
- use m_die,only : die
- implicit none
- ! !INPUT PARAMETERS:
- type(List), intent(in) :: inList
- ! !REVISION HISTORY:
- ! 14Dec01 - J. Larson <larson@mcs.anl.gov> - inital version
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::allocated_'
- allocated_ = associated(inList%bf) .and. associated(inList%lc)
- end function allocated_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: copy_ - Copy a List
- !
- ! !DESCRIPTION:
- ! This routine copies the contents of the input {\tt List} argument
- ! {\tt xL} into the output {\tt List} argument {\tt yL}.
- !
- ! !INTERFACE:
- subroutine copy_(yL,xL) ! yL=xL
- ! !USES:
- !
- use m_die,only : die
- use m_stdio
- use m_String ,only : String
- use m_String ,only : String_clean
- use m_mall,only : mall_mci,mall_ison
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List),intent(in) :: xL
- ! !OUTPUT PARAMETERS:
- !
- type(List),intent(out) :: yL
- ! !REVISION HISTORY:
- ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- ! 16May01 - J. Larson <larson@mcs.anl.gov> - simpler, working
- ! version that exploits the String datatype (see m_String)
- ! 1Aug02 - Larson/Ong - Added logic for correct copying of blank
- ! Lists.
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::copy_'
- type(String) DummStr
- if(size(xL%lc,2) > 0) then
- ! Download input List info from xL to String DummStr
- call getall_(DummStr,xL)
- ! Initialize yL from DummStr
- call initStr_(yL,DummStr)
- call String_clean(DummStr)
- else
- if(size(xL%lc,2) < 0) then ! serious error...
- write(stderr,'(2a,i8)') myname_, &
- ':: FATAL size(xL%lc,2) = ',size(xL%lc,2)
- endif
- ! Initialize yL as a blank list
- call init_(yL, ' ')
- endif
- end subroutine copy_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: exportToChar_ - Export List to a CHARACTER
- !
- ! !DESCRIPTION: This function returns the character buffer portion of
- ! the input {\tt List} argument {\tt inList}---that is, the contents of
- ! {\tt inList\%bf}---as a {\tt CHARACTER} (suitable for printing). An
- ! example of the use of this function is:
- ! \begin{verbatim}
- ! write(stdout,'(1a)') exportToChar(inList)
- ! \end{verbatim}
- ! which writes the contents of {\tt inList\%bf} to the Fortran device
- ! {\tt stdout}.
- !
- ! !INTERFACE:
- function exportToChar_(inList)
- ! !USES:
- !
- use m_die, only : die
- use m_stdio, only : stderr
- use m_String, only : String
- use m_String, only : String_ToChar => toChar
- use m_String, only : String_clean
- implicit none
- ! ! INPUT PARAMETERS:
- type(List), intent(in) :: inList
- ! ! OUTPUT PARAMETERS:
- character(len=size(inList%bf,1)) :: exportToChar_
- ! !REVISION HISTORY:
- ! 13Feb02 - J. Larson <larson@mcs.anl.gov> - initial version.
- ! 06Jun03 - R. Jacob <jacob@mcs.anl.gov> - return blank if List is not allocated
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::exportToChar_'
- type(String) DummStr
- ! Download input List info from inList to String DummStr
- if(allocated_(inList)) then
- call getall_(DummStr,inList)
- exportToChar_ = String_ToChar(DummStr)
- call String_clean(DummStr)
- else
- exportToChar_ = ''
- endif
- end function exportToChar_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: exportToString_ - Export List to a String
- !
- ! !DESCRIPTION: This function returns the character buffer portion of
- ! the input {\tt List} argument {\tt inList}---that is, the contents of
- ! {\tt inList\%bf}---as a {\tt String} (see the mpeu module m\_String
- ! for more information regarding the {\tt String} type). This function
- ! was created to circumvent problems with implementing inheritance of
- ! the function {\tt exportToChar\_()} to other datatypes build on top
- ! of the {\tt List} type.
- !
- ! !INTERFACE:
- function exportToString_(inList)
- ! !USES:
- !
- use m_die, only : die
- use m_stdio, only : stderr
- use m_String, only : String
- use m_String, only : String_init => init
- implicit none
- ! ! INPUT PARAMETERS:
- type(List), intent(in) :: inList
- ! ! OUTPUT PARAMETERS:
- type(String) :: exportToString_
- ! !REVISION HISTORY:
- ! 14Aug02 - J. Larson <larson@mcs.anl.gov> - initial version.
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::exportToString_'
- if(allocated_(inList)) then
- call getall_(exportToString_, inList)
- else
- call String_init(exportToString_, 'NOTHING')
- endif
- end function exportToString_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: CharBufferSize_ - Return size of a List's Character Buffer
- !
- ! !DESCRIPTION: This function returns the length of the character
- ! buffer portion of the input {\tt List} argument {\tt inList} (that
- ! is, the number of characters stored in {\tt inList\%bf}) as an
- ! {\tt INTEGER}. Suppose for the sake of argument that {\tt inList}
- ! was created using the following call to {\tt init\_()}:
- ! \begin{verbatim}
- ! call init_(inList, 'Groucho:Harpo:Chico:Zeppo')
- ! \end{verbatim}
- ! Then, using the above example value of {\tt inList}, we can use
- ! {\tt CharBufferSize\_()} as follows:
- ! \begin{verbatim}
- ! integer :: BufferLength
- ! BufferLength = CharBufferSize(inList)
- ! \end{verbatim}
- ! and the resulting value of {\tt BufferLength} will be 25.
- !
- ! !INTERFACE:
- integer function CharBufferSize_(inList)
- ! !USES:
- !
- use m_die, only : die
- use m_stdio, only : stderr
- implicit none
- ! ! INPUT PARAMETERS:
- type(List), intent(in) :: inList
- ! !REVISION HISTORY:
- ! 13Feb02 - J. Larson <larson@mcs.anl.gov> - initial version.
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::CharBufferSize_'
- if(allocated_(inList)) then
- CharBufferSize_ = size(inList%bf)
- else
- write(stderr,'(2a)') myname_,":: Argument inList not allocated."
- call die(myname_)
- endif
- end function CharBufferSize_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: get_ - Retrieve a Numbered Item from a List as a String
- !
- ! !DESCRIPTION:
- ! This routine retrieves a numbered item (defined by the input
- ! {\tt INTEGER} argument {\tt ith}) from the input {\tt List} argument
- ! {\tt aList}, and returns it in the output {\tt String} argument
- ! {\tt itemStr} (see the module {\tt m\_String} for more information
- ! about the {\tt String} type). If the argument {\tt ith} is nonpositive,
- ! or greater than the number of items in {\tt aList}, a String containing
- ! one blank space is returned.
- !
- ! !INTERFACE:
- subroutine get_(itemStr, ith, aList)
- ! !USES:
- !
- use m_String, only : String, init, toChar
- implicit none
- ! !INPUT PARAMETERS:
- !
- integer, intent(in) :: ith
- type(List), intent(in) :: aList
- ! !OUTPUT PARAMETERS:
- !
- type(String),intent(out) :: itemStr
- ! !REVISION HISTORY:
- ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- ! 14May07 - Larson, Jacob - add space to else case string so function
- ! matches documentation.
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::get_'
- integer :: lb,le
- if(ith>0 .and. ith <= size(aList%lc,2)) then
- lb=aList%lc(0,ith)
- le=aList%lc(1,ith)
- call init(itemStr,toChar(aList%bf(lb:le)))
- else
- call init(itemStr,' ')
- endif
- end subroutine get_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: getall_ - Return all Items from a List as one String
- !
- ! !DESCRIPTION:
- ! This routine returns all the items from the input {\tt List} argument
- ! {\tt aList} in the output {\tt String} argument {\tt itemStr} (see
- ! the module {\tt m\_String} for more information about the {\tt String}
- ! type). The contents of the character buffer in {\tt itemStr} will
- ! be the all of the items in {\tt aList}, separated by the colon delimiter.
- !
- ! !INTERFACE:
- subroutine getall_(itemStr, aList)
- ! !USES:
- !
- use m_String, only : String, init, toChar
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: aList
- ! !OUTPUT PARAMETERS:
- !
- type(String), intent(out) :: itemStr
- ! !REVISION HISTORY:
- ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::getall_'
- integer :: lb,le,ni
- ni=size(aList%lc,2)
- lb=aList%lc(0,1)
- le=aList%lc(1,ni)
- call init(itemStr,toChar(aList%bf(lb:le)))
- end subroutine getall_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: getrange_ - Return a Range of Items from a List as one String
- !
- ! !DESCRIPTION:
- ! This routine returns all the items ranked {\tt i1} through {\tt i2}
- ! from the input {\tt List} argument {\tt aList} in the output
- ! {\tt String} argument {\tt itemStr} (see the module {\tt m\_String}
- ! for more information about the {\tt String} type). The contents of
- ! the character buffer in {\tt itemStr} will be items in {\tt i1} through
- ! {\tt i2} {\tt aList}, separated by the colon delimiter.
- !
- ! !INTERFACE:
- subroutine getrange_(itemStr, i1, i2, aList)
- ! !USES:
- !
- use m_die, only : die
- use m_stdio, only : stderr
- use m_String, only : String,init,toChar
- implicit none
- ! !INPUT PARAMETERS:
- !
- integer, intent(in) :: i1
- integer, intent(in) :: i2
- type(List), intent(in) :: aList
- ! !OUTPUT PARAMETERS:
- !
- type(String),intent(out) :: itemStr
- ! !REVISION HISTORY:
- ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- ! 26Jul02 - J. Larson - Added argument checks.
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::getrange_'
- integer :: lb,le,ni
- ! Argument Sanity Checks:
- if(.not. allocated_(aList)) then
- write(stderr,'(2a)') myname_, &
- ':: FATAL--List argument aList is not initialized.'
- call die(myname_)
- endif
- ! is i2 >= i1 as we assume?
- if(i1 > i2) then
- write(stderr,'(2a,2(a,i8))') myname_, &
- ':: FATAL. Starting/Ending item ranks are out of order; ', &
- 'i2 must be greater or equal to i1. i1 =',i1,' i2 = ',i2
- call die(myname_)
- endif
- ni=size(aList%lc,2) ! the number of items in aList...
- ! is i1 or i2 too big?
- if(i1 > ni) then
- write(stderr,'(2a,2(a,i8))') myname_, &
- ':: FATAL--i1 is greater than the number of items in ', &
- 'The List argument aList: i1 =',i1,' ni = ',ni
- call die(myname_)
- endif
- if(i2 > ni) then
- write(stderr,'(2a,2(a,i8))') myname_, &
- ':: FATAL--i2 is greater than the number of items in ', &
- 'The List argument aList: i2 =',i2,' ni = ',ni
- call die(myname_)
- endif
- ! End of Argument Sanity Checks.
- lb=aList%lc(0,max(1,i1))
- le=aList%lc(1,min(ni,i2))
- call init(itemStr,toChar(aList%bf(lb:le)))
- end subroutine getrange_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: identical_ - Compare Two Lists for Equality
- !
- ! !DESCRIPTION:
- ! This function compares the string buffer and indexing information in
- ! the two input {\tt List} arguments {\tt yL} and {\tt xL}. If the
- ! string buffers and index buffers of {\tt yL} and {\tt xL} match, this
- ! function returns a value of {\tt .TRUE.} Otherwise, it returns a
- ! value of {\tt .FALSE.}
- !
- ! !INTERFACE:
- logical function identical_(yL, xL)
- ! !USES:
- !
- use m_die,only : die
- use m_String ,only : String
- use m_String ,only : String_clean
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: yL
- type(List), intent(in) :: xL
- ! !REVISION HISTORY:
- ! 14Oct01 - J. Larson <larson@mcs.anl.gov> - original version
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::identical_'
- logical :: myIdentical
- type(String) :: DummStr
- integer :: n, NumItems
- ! Compare the number of the items in the Lists xL and yL.
- ! If they differ, myIdentical is set to .FALSE. and we are
- ! finished. If both Lists sport the same number of items,
- ! we must compare them one-by-one...
- myIdentical = .FALSE.
- if(nitem_(yL) == nitem_(xL)) then
- NumItems = nitem_(yL)
- COMPARE_LOOP: do n=1,NumItems
- call get_(DummStr, n, yL) ! retrieve nth tag as a String
- if( indexStr_(xL, Dummstr) /= n ) then ! a discrepency spotted.
- call String_clean(Dummstr)
- myIdentical = .FALSE.
- EXIT
- else
- call String_clean(Dummstr)
- endif
- myIdentical = .TRUE. ! we survived the whole test process.
- end do COMPARE_LOOP
- endif
- identical_ = myIdentical
- end function identical_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: get_indices_ - Index Multiple Items in a List
- !
- ! !DESCRIPTION: This routine takes as input a {\tt List} argument
- ! {\tt aList}, and a {\tt CHARACTER} string {Values}, which is a colon-
- ! delimited string of items, and returns an {\tt INTEGER} array
- ! {\tt indices(:)}, which contain the rank of each item in {\tt aList}.
- ! For example, suppose {\tt aList} was created from the character string
- ! \begin{verbatim}
- ! 'happy:sleepy:sneezey:grumpy:dopey::bashful:doc'
- ! \end{verbatim}
- ! and get\_indices\_() is invoked as follows:
- ! \begin{verbatim}
- ! call get_indices_(indices, aList, 'sleepy:grumpy:bashful:doc')
- ! \end{verbatim}
- ! The array {\tt indices(:)} will be returned with 4 entries:
- ! ${\tt indices(1)}=2$, ${\tt indices(2)}=4$, ${\tt indices(3)}=6$, and
- ! ${\tt indices(4)}=7$.
- !
- ! {\bf N.B.}: This routine operates on the assumption that each of the
- ! substrings in the colon-delimited string {\tt Values} is an item in
- ! {\tt aList}. If this assumption is invalid, this routine terminates
- ! execution with an error message.
- !
- ! {\bf N.B.}: The pointer {\tt indices} must be {\tt UNASSOCIATED} on entry
- ! to this routine, and will be {\tt ASSOCIATED} upon return. After this pointer
- ! is no longer needed, it should be deallocated. Failure to do so will result
- ! in a memory leak.
- !
- ! !INTERFACE:
- subroutine get_indices_(indices, aList, Values)
- ! !USES:
- !
- use m_stdio
- use m_die
- use m_String, only : String
- use m_String, only : String_clean => clean
- use m_String, only : String_toChar => toChar
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: aList ! an indexed string values
- character(len=*), intent(in) :: Values ! ":" delimited names
- ! !OUTPUT PARAMETERS:
- !
- integer, dimension(:), pointer :: indices
- ! !REVISION HISTORY:
- ! 31May98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
- ! 12Feb03 - J. Larson <larson@mcs.anl.gov> Working refactored version
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::get_indices_'
- type(List) :: tList
- type(String) :: tStr
- integer :: i, ierr, n
- ! Create working list based on input colon-delimited string
- call init_(tList, values)
- ! Count items in tList and allocate indices(:) accordingly
- n = nitem_(tList)
- if(n > nitem_(aList)) then
- write(stderr,'(5a,2(i8,a))') myname_, &
- ':: FATAL--more items in argument Values than aList! Input string', &
- 'Values = "',Values,'" has ',n,' items. aList has ',nitem_(aList), &
- ' items.'
- call die(myname_)
- endif
- allocate(indices(n), stat=ierr)
- if(ierr /= 0) then
- write(stderr,'(2a,i8,a)') myname_, &
- ':: FATAL--allocate(indices(...) failed with stat=',ierr,&
- '. On entry to this routine, this pointer must be NULL.'
- call die(myname_)
- endif
- ! Retrieve each item from tList as a String and index it
- do i=1,n
- call get_(tStr,i,tList)
- indices(i) = indexStr_(aList,tStr)
- if(indices(i) == 0) then ! ith item not present in aList!
- write(stderr,'(4a)') myname_, &
- ':: FATAL--item "',String_toChar(tStr),'" not found.'
- call die(myname_)
- endif
- call String_clean(tStr)
- end do
- ! Clean up temporary List tList
- call clean_(tList)
- end subroutine get_indices_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: test_indices_ - Test/Index Multiple Items in a List
- !
- ! !DESCRIPTION: This routine takes as input a {\tt List} argument
- ! {\tt aList}, and a {\tt CHARACTER} string {Values}, which is a colon-
- ! delimited string of items, and returns an {\tt INTEGER} array
- ! {\tt indices(:)}, which contain the rank of each item in {\tt aList}.
- ! For example, suppose {\tt aList} was created from the character string
- ! \begin{verbatim}
- ! 'happy:sleepy:sneezey:grumpy:dopey::bashful:doc'
- ! \end{verbatim}
- ! and {\tt test\_indices\_()} is invoked as follows:
- ! \begin{verbatim}
- ! call test_indices_(indices, aList, 'sleepy:grumpy:bashful:doc')
- ! \end{verbatim}
- ! The array {\tt indices(:)} will be returned with 4 entries:
- ! ${\tt indices(1)}=2$, ${\tt indices(2)}=4$, ${\tt indices(3)}=6$, and
- ! ${\tt indices(4)}=7$.
- !
- ! Now suppose {\tt test\_indices\_()} is invoked as follows:
- ! \begin{verbatim}
- ! call test_indices_(indices, aList, 'sleepy:grumpy:bashful:Snow White')
- ! \end{verbatim}
- ! The array {\tt indices(:)} will be returned with 4 entries:
- ! ${\tt indices(1)}=2$, ${\tt indices(2)}=4$, ${\tt indices(3)}=6$, and
- ! ${\tt indices(4)}=0$.
- !
- ! {\bf N.B.}: This routine operates on the assumption that one or more
- ! of the substrings in the colon-delimited string {\tt Values} is may not
- ! be an item in {\tt aList}. If an item in {\tt Values} is {\em not} in
- ! {\tt aList}, its corresponding entry in {\tt indices(:)} is set to zero.
- !
- ! {\bf N.B.}: The pointer {\tt indices} must be {\tt UNASSOCIATED} on entry
- ! to this routine, and will be {\tt ASSOCIATED} upon return. After this pointer
- ! is no longer needed, it should be deallocated. Failure to do so will result
- ! in a memory leak.
- !
- ! !INTERFACE:
- subroutine test_indices_(indices, aList, Values)
- ! !USES:
- !
- use m_stdio
- use m_die
- use m_String, only : String
- use m_String, only : String_clean => clean
- use m_String, only : String_toChar => toChar
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: aList ! an indexed string values
- character(len=*), intent(in) :: Values ! ":" delimited names
- ! !OUTPUT PARAMETERS:
- !
- integer, dimension(:), pointer :: indices
- ! !REVISION HISTORY:
- ! 12Feb03 - J. Larson <larson@mcs.anl.gov> Working refactored version
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::test_indices_'
- type(List) :: tList
- type(String) :: tStr
- integer :: i, ierr, n
- ! Create working list based on input colon-delimited string
- call init_(tList, values)
- ! Count items in tList and allocate indices(:) accordingly
- n = nitem_(tList)
- allocate(indices(n), stat=ierr)
- if(ierr /= 0) then
- write(stderr,'(2a,i8,a)') myname_, &
- ':: FATAL--allocate(indices(...) failed with stat=',ierr,&
- '. On entry to this routine, this pointer must be NULL.'
- call die(myname_)
- endif
- ! Retrieve each item from tList as a String and index it
- do i=1,n
- call get_(tStr,i,tList)
- indices(i) = indexStr_(aList,tStr)
- call String_clean(tStr)
- end do
- ! Clean up temporary List tList
- call clean_(tList)
- end subroutine test_indices_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! Math and Computer Science Division, Argonne National Laboratory !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: append_ - Append One List Onto the End of Another
- !
- ! !DESCRIPTION: This routine takes two {\tt List} arguments
- ! {\tt iList1} and {\tt iList2}, and appends {\tt List2} onto
- ! the end of {\tt List1}.
- !
- ! {\bf N.B.}: There is no check for shared items in the arguments
- ! {\tt List1} and {\tt List2}. It is the user's responsibility to
- ! ensure {\tt List1} and {\tt List2} share no items. If this routine
- ! is invoked in such a manner that {\tt List1} and {\tt List2} share
- ! common items, the resultant value of {\tt List1} will produce
- ! ambiguous results for some of the {\tt List} query functions.
- !
- ! {\bf N.B.}: The outcome of this routine is order dependent. That is,
- ! the entries of {\tt iList2} will follow the {\em input} entries in
- ! {\tt iList1}.
- !
- ! !INTERFACE:
- subroutine append_(iList1, iList2)
- !
- ! !USES:
- !
- use m_stdio
- use m_die, only : die
- use m_mpif90
- use m_String, only: String
- use m_String, only: String_toChar => toChar
- use m_String, only: String_len
- use m_String, only: String_clean => clean
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: iList2
- ! !INPUT/OUTPUT PARAMETERS:
- !
- type(List), intent(inout) :: iList1
- ! !REVISION HISTORY:
- ! 6Aug02 - J. Larson - Initial version
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::append_'
- type(List) :: DummyList
- call copy_(DummyList, iList1)
- call clean_(iList1)
- call concatenate(DummyList, iList2, iList1)
- call clean_(DummyList)
- end subroutine append_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! Math and Computer Science Division, Argonne National Laboratory !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: concatenate_ - Concatenates two Lists to form a Third List.
- !
- ! !DESCRIPTION: This routine takes two input {\tt List} arguments
- ! {\tt iList1} and {\tt iList2}, and concatenates them, producing an
- ! output {\tt List} argument {\tt oList}.
- !
- ! {\bf N.B.}: The nature of this routine is such that one must
- ! {\bf never} supply as the actual value of {\tt oList} the same
- ! value supplied for either {\tt iList1} or {\tt iList2}.
- !
- ! {\bf N.B.}: The outcome of this routine is order dependent. That is,
- ! the entries of {\tt iList2} will follow {\tt iList1}.
- !
- ! !INTERFACE:
- subroutine concatenate_(iList1, iList2, oList)
- !
- ! !USES:
- !
- use m_stdio
- use m_die, only : die
- use m_mpif90
- use m_String, only: String
- use m_String, only: String_init => init
- use m_String, only: String_clean => clean
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: iList1
- type(List), intent(in) :: iList2
- ! !OUTPUT PARAMETERS:
- !
- type(List), intent(out) :: oList
- ! !BUGS: For now, the List concatenate algorithm relies on fixed-length
- ! CHARACTER variables as intermediate storage. The lengths of these
- ! scratch variables is hard-wired to 10000, which should be large enough
- ! for most applications. This undesirable feature should be corrected
- ! ASAP.
- !
- ! !REVISION HISTORY:
- ! 8May01 - J.W. Larson - initial version.
- ! 17May01 - J.W. Larson - Re-worked and tested successfully.
- ! 17Jul02 - E. Ong - fixed the bug mentioned above
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::concatenate_'
- character, dimension(:), allocatable :: CatBuff
- integer :: CatBuffLength, i, ierr, Length1, Length2
- type(String) :: CatString
- ! First, handle the case of either iList1 and/or iList2 being
- ! null
- if((nitem_(iList1) == 0) .or. (nitem_(iList2) == 0)) then
- if((nitem_(iList1) == 0) .and. (nitem_(iList2) == 0)) then
- call init_(oList,'')
- else
- if((nitem_(iList1) == 0) .and. (nitem_(iList2) > 0)) then
- call copy_(oList, iList2)
- endif
- if((nitem_(iList1) > 0) .and. (nitem_(iList2) == 0)) then
- call copy_(oList,iList1)
- endif
- endif
- else ! both lists are non-null
- ! Step one: Get lengths of character buffers of iList1 and iList2:
- Length1 = CharBufferSize_(iList1)
- Length2 = CharBufferSize_(iList2)
- ! Step two: create CatBuff(:) as workspace
- CatBuffLength = Length1 + Length2 + 1
- allocate(CatBuff(CatBuffLength), stat=ierr)
- if(ierr /= 0) then
- write(stderr,'(2a,i8)') myname_, &
- ':: FATAL--allocate(CatBuff(...) failed. ierr=',ierr
- call die(myname_)
- endif
- ! Step three: concatenate CHARACTERs with the colon separator
- ! into CatBuff(:)
- do i=1,Length1
- CatBuff(i) = iList1%bf(i)
- end do
- CatBuff(Length1 + 1) = ':'
- do i=1,Length2
- CatBuff(Length1 + 1 + i) = iList2%bf(i)
- end do
- ! Step four: initialize a String CatString:
- call String_init(CatString, CatBuff)
- ! Step five: initialize oList:
- call initStr_(oList, CatString)
- ! The concatenation is complete. Now, clean up
- call String_clean(CatString)
- deallocate(CatBuff,stat=ierr)
- if(ierr /= 0) then
- write(stderr,'(2a,i8)') myname_, &
- ':: FATAL--deallocate(CatBuff) failed. ierr=',ierr
- call die(myname_)
- endif
- endif
- end subroutine concatenate_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! Math and Computer Science Division, Argonne National Laboratory !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: bcast_ - MPI Broadcast for the List Type
- !
- ! !DESCRIPTION: This routine takes an input {\tt List} argument
- ! {\tt iList} (on input, valid on the root only), and broadcasts it.
- !
- ! {\bf N.B.}: The outcome of this routine, {\tt ioList} on non-root
- ! processes, represents allocated memory. When this {\tt List} is
- ! no longer needed, it must be deallocated by invoking the routine
- ! {\tt List\_clean()}. Failure to do so will cause a memory leak.
- !
- ! !INTERFACE:
- subroutine bcast_(ioList, root, comm, status)
- !
- ! !USES:
- !
- use m_stdio, only : stderr
- use m_die, only : MP_perr_die, die
- use m_String, only: String
- use m_String, only: String_bcast => bcast
- use m_String, only: String_clean => clean
- use m_mpif90
- implicit none
- ! !INPUT PARAMETERS:
- !
- integer, intent(in) :: root
- integer, intent(in) :: comm
- ! !INPUT/OUTPUT PARAMETERS:
- !
- type(List), intent(inout) :: ioList
- ! !OUTPUT PARAMETERS:
- !
- integer, optional, intent(out) :: status
- ! !REVISION HISTORY:
- ! 7May01 - J.W. Larson - initial version.
- ! 14May01 - R.L. Jacob - fix error checking
- ! 16May01 - J.W. Larson - new, simpler String-based algorigthm
- ! (see m_String for details), which works properly on
- ! the SGI platform.
- ! 13Jun01 - J.W. Larson <larson@mcs.anl.gov> - Initialize status
- ! (if present).
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::bcast_'
- integer :: myID, ierr
- type(String) :: DummStr
- ! Initialize status (if present)
- if(present(status)) status = 0
- ! Which process am I?
- call MPI_COMM_RANK(comm, myID, ierr)
- if(ierr /= 0) then
- if(present(status)) then
- status = ierr
- write(stderr,'(2a,i4)') myname_,":: MPI_COMM_RANK(), ierr=",ierr
- return
- else
- call MP_perr_die(myname_,"MPI_COMM_RANK()",ierr)
- endif
- endif
- ! on the root, convert ioList into the String variable DummStr
- if(myID == root) then
- if(CharBufferSize_(ioList) <= 0) then
- call die(myname_, 'Attempting to broadcast an empty list!',&
- CharBufferSize_(ioList))
- endif
- call getall_(DummStr, ioList)
- endif
- ! Broadcast DummStr
- call String_bcast(DummStr, root, comm, ierr)
- if(ierr /= 0) then
- if(present(status)) then
- status = ierr
- write(stderr,'(2a,i4)') myname_,":: call String_bcast(), ierr=",ierr
- return
- else
- call MP_perr_die(myname_,"String_bcast() failed, stat=",ierr)
- endif
- endif
- ! Initialize ioList off the root using DummStr
- if(myID /= root) then
- call initStr_(ioList, DummStr)
- endif
- ! And now, the List broadcast is complete.
- call String_clean(DummStr)
- end subroutine bcast_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! Math and Computer Science Division, Argonne National Laboratory !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: send_ - MPI Point-to-Point Send for the List Type
- !
- ! !DESCRIPTION: This routine takes an input {\tt List} argument
- ! {\tt inList} and sends it to processor {\tt dest} on the communicator
- ! associated with the fortran 90 {\tt INTEGER} handle {\tt comm}. The
- ! message is tagged by the input {\tt INTEGER} argument {\tt TagBase}.
- ! The success (failure) of this operation is reported in the zero
- ! (nonzero) optional output argument {\tt status}.
- !
- ! {\bf N.B.}: One must avoid assigning elsewhere the MPI tag values
- ! {\tt TagBase} and {\tt TagBase+1}. This is because {\tt send\_()}
- ! performs the send of the {\tt List} as a pair of operations. The
- ! first send is the number of characters in {\tt inList\%bf}, and is
- ! given MPI tag value {\tt TagBase}. The second send is the
- ! {\tt CHARACTER} data present in {\tt inList\%bf}, and is given MPI
- ! tag value {\tt TagBase+1}.
- !
- ! !INTERFACE:
- subroutine send_(inList, dest, TagBase, comm, status)
- !
- ! !USES:
- !
- use m_stdio
- use m_die, only : MP_perr_die
- use m_mpif90
- use m_String, only: String
- use m_String, only: String_toChar => toChar
- use m_String, only: String_len
- use m_String, only: String_clean => clean
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: inList
- integer, intent(in) :: dest
- integer, intent(in) :: TagBase
- integer, intent(in) :: comm
- ! !OUTPUT PARAMETERS:
- !
- integer, optional, intent(out) :: status
- ! !REVISION HISTORY:
- ! 6Jun01 - J.W. Larson - initial version.
- ! 13Jun01 - J.W. Larson <larson@mcs.anl.gov> - Initialize status
- ! (if present).
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::send_'
- type(String) :: DummStr
- integer :: ierr, length
- ! Set status flag to zero (success) if present:
- if(present(status)) status = 0
- ! Step 1. Extract CHARACTER buffer from inList and store it
- ! in String variable DummStr, determine its length.
- call getall_(DummStr, inList)
- length = String_len(DummStr)
- ! Step 2. Send Length of String DummStr to process dest.
- call MPI_SEND(length, 1, MP_type(length), dest, TagBase, comm, ierr)
- if(ierr /= 0) then
- if(present(status)) then
- write(stderr,'(2a,i8)') myname_, &
- ':: MPI_SEND(length...) failed. ierror=', ierr
- status = ierr
- return
- else
- call MP_perr_die(myname_,':: MPI_SEND(length...) failed',ierr)
- endif
- endif
- ! Step 3. Send CHARACTER portion of String DummStr
- ! to process dest.
- call MPI_SEND(DummStr%c(1), length, MP_CHARACTER, dest, TagBase+1, &
- comm, ierr)
- if(ierr /= 0) then
- if(present(status)) then
- write(stderr,'(2a,i8)') myname_, &
- ':: MPI_SEND(DummStr%c...) failed. ierror=', ierr
- status = ierr
- return
- else
- call MP_perr_die(myname_,':: MPI_SEND(DummStr%c...) failed',ierr)
- endif
- endif
- end subroutine send_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! Math and Computer Science Division, Argonne National Laboratory !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: recv_ - MPI Point-to-Point Receive for the List Type
- !
- ! !DESCRIPTION: This routine receives the output {\tt List} argument
- ! {\tt outList} from processor {\tt source} on the communicator associated
- ! with the fortran 90 {\tt INTEGER} handle {\tt comm}. The message is
- ! tagged by the input {\tt INTEGER} argument {\tt TagBase}. The success
- ! (failure) of this operation is reported in the zero (nonzero) optional
- ! output argument {\tt status}.
- !
- ! {\bf N.B.}: One must avoid assigning elsewhere the MPI tag values
- ! {\tt TagBase} and {\tt TagBase+1}. This is because {\tt recv\_()}
- ! performs the receive of the {\tt List} as a pair of operations. The
- ! first receive is the number of characters in {\tt outList\%bf}, and
- ! is given MPI tag value {\tt TagBase}. The second receive is the
- ! {\tt CHARACTER} data present in {\tt outList\%bf}, and is given MPI
- ! tag value {\tt TagBase+1}.
- !
- ! !INTERFACE:
- subroutine recv_(outList, source, TagBase, comm, status)
- !
- ! !USES:
- !
- use m_stdio, only : stderr
- use m_die, only : MP_perr_die
- use m_mpif90
- use m_String, only : String
- implicit none
- ! !INPUT PARAMETERS:
- !
- integer, intent(in) :: source
- integer, intent(in) :: TagBase
- integer, intent(in) :: comm
- ! !OUTPUT PARAMETERS:
- !
- type(List), intent(out) :: outList
- integer, optional, intent(out) :: status
- ! !REVISION HISTORY:
- ! 6Jun01 - J.W. Larson - initial version.
- ! 11Jun01 - R. Jacob - small bug fix; status in MPI_RECV
- ! 13Jun01 - J.W. Larson <larson@mcs.anl.gov> - Initialize status
- ! (if present).
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::recv_'
- integer :: ierr, length
- integer :: MPstatus(MP_STATUS_SIZE)
- type(String) :: DummStr
- ! Initialize status to zero (success), if present.
- if(present(status)) status = 0
- ! Step 1. Receive Length of String DummStr from process source.
- call MPI_RECV(length, 1, MP_type(length), source, TagBase, comm, &
- MPstatus, ierr)
- if(ierr /= 0) then
- if(present(status)) then
- write(stderr,'(2a,i8)') myname_, &
- ':: MPI_RECV(length...) failed. ierror=', ierr
- status = ierr
- return
- else
- call MP_perr_die(myname_,':: MPI_RECV(length...) failed',ierr)
- endif
- endif
- allocate(DummStr%c(length), stat=ierr)
- ! Step 2. Send CHARACTER portion of String DummStr
- ! to process dest.
- call MPI_RECV(DummStr%c(1), length, MP_CHARACTER, source, TagBase+1, &
- comm, MPstatus, ierr)
- if(ierr /= 0) then
- if(present(status)) then
- write(stderr,'(2a,i8)') myname_, &
- ':: MPI_RECV(DummStr%c...) failed. ierror=', ierr
- status = ierr
- return
- else
- call MP_perr_die(myname_,':: MPI_RECV(DummStr%c...) failed',ierr)
- endif
- endif
- ! Step 3. Initialize outList.
- call initStr_(outList, DummStr)
- end subroutine recv_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! Math and Computer Science Division, Argonne National Laboratory !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: GetSharedListIndices_ - Index Shared Items for Two Lists
- !
- ! !DESCRIPTION: {\tt GetSharedListIndices\_()} compares two user-
- ! supplied {\tt List} arguments {\tt List1} and {\tt Lis2} to determine:
- ! the number of shared items {\tt NumShared}, and arrays of the locations
- ! {\tt Indices1} and {\tt Indices2} in {\tt List1} and {\tt List2},
- ! respectively.
- !
- ! {\bf N.B.:} This routine returns two allocated arrays: {\tt Indices1(:)}
- ! and {\tt Indices2(:)}. Both of these arrays must be deallocated once they
- ! are no longer needed. Failure to do this will create a memory leak.
- !
- ! !INTERFACE:
- subroutine GetSharedListIndices_(List1, List2, NumShared, Indices1, &
- Indices2)
- !
- ! !USES:
- !
- use m_die, only : MP_perr_die, die, warn
- use m_String, only : String
- use m_String, only : String_clean => clean
- implicit none
- ! !INPUT PARAMETERS:
- !
- type(List), intent(in) :: List1
- type(List), intent(in) :: List2
- ! !OUTPUT PARAMETERS:
- !
- integer, intent(out) :: NumShared
- integer,dimension(:), pointer :: Indices1
- integer,dimension(:), pointer :: Indices2
- ! !REVISION HISTORY:
- ! 7Feb01 - J.W. Larson <larson@mcs.anl.gov> - initial version
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::GetSharedListIndices_'
- ! Error flag
- integer :: ierr
- ! number of items in List1 and List2, respectively:
- integer :: nitem1, nitem2
- ! MAXIMUM number of matches possible:
- integer :: NumSharedMax
- ! Temporary storage for a string tag retrieved from a list:
- type(String) :: tag
- ! Loop counters / temporary indices:
- integer :: n1, n2
- ! Determine the number of items in each list:
- nitem1 = nitem_(List1)
- nitem2 = nitem_(List2)
- ! The maximum number of list item matches possible
- ! is the minimum(nitem1,nitem2):
- NumSharedMax = min(nitem1,nitem2)
- ! Allocate sufficient space for the matches we may find:
- allocate(Indices1(NumSharedMax), Indices2(NumSharedMax), stat=ierr)
- if(ierr /= 0) call die(myname_,'allocate() Indices1 and 2',ierr)
- ! Initialize the counter for the number of matches found:
- NumShared = 0
- ! Scan through the two lists. For the sake of speed, loop
- ! over the shorter of the two lists...
- if(nitem1 <= nitem2) then ! List1 is shorter--scan it...
- do n1=1,NumSharedMax
- ! Retrieve string tag n1 from List1:
- call get_(tag, n1, List1)
- ! Index this tag WRT List2--a nonzero value signifies a match
- n2 = indexStr_(List2, tag)
- ! Clear out tag for the next iteration...
- call String_clean(tag)
- ! If we have a hit, update NumShared, and load the indices
- ! n1 and n2 in Indices1 and Indices2, respectively...
- if((0 < n2) .and. (n2 <= nitem2)) then
- NumShared = NumShared + 1
- Indices1(NumShared) = n1
- Indices2(NumShared) = n2
- endif
- end do ! do n1=1,NumSharedMax
- else ! List1 is shorter--scan it...
- do n2=1,NumSharedMax
- ! Retrieve string tag n2 from List2:
- call get_(tag, n2, List2)
- ! Index this tag WRT List1--a nonzero value signifies a match
- n1 = indexStr_(List1, tag)
- ! Clear out tag for the next iteration...
- call String_clean(tag)
- ! If we have a hit, update NumShared, and load the indices
- ! n1 and n2 in Indices1 and Indices2, respectively...
- if((0 < n1) .and. (n1 <= nitem1)) then
- NumShared = NumShared + 1
- Indices1(NumShared) = n1
- Indices2(NumShared) = n2
- endif
- end do ! do n2=1,NumSharedMax
- endif ! if(nitem1 <= nitem2)...
- end subroutine GetSharedListIndices_
- end module m_List
- !.
|