📄 generic_list.f90
字号:
! SEM2DPACK version 2.2.11 -- A Spectral Element Method for 2D wave propagation and fracture dynamics,! with emphasis on computational seismology and earthquake source dynamics.! ! Copyright (C) 2003-2007 Jean-Paul Ampuero! All Rights Reserved! ! Jean-Paul Ampuero! ! ETH Zurich (Swiss Federal Institute of Technology)! Institute of Geophysics! Seismology and Geodynamics Group! ETH H鰊ggerberg HPP O 13.1! CH-8093 Z黵ich! Switzerland! ! ampuero@erdw.ethz.ch! +41 44 633 2197 (office)! +41 44 633 1065 (fax)! ! http://www.sg.geophys.ethz.ch/geodynamics/ampuero/! ! ! This software is freely available for scientific research purposes. ! If you use this software in writing scientific papers include proper ! attributions to its author, Jean-Paul Ampuero.! ! This program is free software; you can redistribute it and/or! modify it under the terms of the GNU General Public License! as published by the Free Software Foundation; either version 2! of the License, or (at your option) any later version.! ! This program is distributed in the hope that it will be useful,! but WITHOUT ANY WARRANTY; without even the implied warranty of! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the! GNU General Public License for more details.! ! You should have received a copy of the GNU General Public License! along with this program; if not, write to the Free Software! Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.! ! From: Roger Young and Peter McGavin, "A generic list implementation"! ACM SIGPLAN Fortran Forum, Volume 20, Issue 1 (April 2001), Pages 16-20! (available online)! See original source for more info and sample at:! http://www.fortran.com/fortran/gen_ll.f90 !!*** WARNING: USES A NON STANDARD FEATURE OF THE transfer INTRINSIC ***! Search the COMP-FORTRAN-90 mailing list archives for more info.! The problem is how to treat generic lists in Fortran 90. ! Lists can be (1) homogeneous (elements all of the same type) or ! (2) heterogeneous.! ! (1) Often there is a need to work with many (homogeneous) lists which! may be of different types. Patrice Lignelet has shown how generic list! properties may be logically treated in Fortran 90. However it still! appears that the list operations (initialization, addition/removal of! elements etc) must be separately defined for each list type, which! leads to considerable duplication of code.! ! (2) Jean Vezina has shown how to handle a heterogeneous list by employing the ! F90 TRANSFER() function. ! ! Peter McGavin at Industrial Research Limited (p.mcgavin@irl.cri.nz)! has constructed a species of generic list for Fortran 90. The method! is based on 2 ideas: the properties of the TRANSFER() function, and! the fact that a pointer to a derived data type also points to the! *first field* within the data type (and conversely). ! ! Since the TRANSFER() function does not accept pointer arguments the! method requires the introduction of 2 auxilliary data types which! contain the pointers, one in the generic list module and one for each! list type in the calling program (the same construction is adopted! when defining "arrays of pointers"). In spite of this complication the! method represents a big saving, both conceptually and practically, when! many lists of different types are involved.! ! To make clear the method we present a simple generic list module! together with a calling program. The list module defines a! uni-directional linked list with a few sample operations, but! obviously more complicated generic lists could be substituted in its! place (eg include back pointers).! ! Roger Young! Peter McGavin! ! .........................................................................MODULE Generic_List! Defines a generic uni-directional linked list IMPLICIT NONEPRIVATEPUBLIC :: & Link_Type, &! Put a Link_Type field first in your structure Link_Ptr_Type, &! Mold this to and from your type ptr with TRANSFER List_Type ! You should declare a List_Type variablePUBLIC :: & LI_Init_List, &! Initialise the List_Type variable before LI_Get_Head, &! Returns the first Link in the list LI_Get_Next, &! Return the next Link after a given one LI_Add_To_Head, &! Add a Link to the head of the list LI_Remove_Head, &! Remove the first Link and return it LI_Get_Len, &! Compute list length LI_Associated, &! Check if list member is associated LI_Nullify, &! Resets a Link pointer to null LI_Check_List, &! Aborts program if list is invalid or corrupt LI_Remove_Next ! Remove next Link from list and return itTYPE Link_Type PRIVATE TYPE(Link_Type), POINTER :: NextEND TYPE Link_Type! Auxilliary data type required for the transfer function TYPE Link_Ptr_Type ! Use TRANSFER() function to mold Link_Ptr_Type PRIVATE ! to your pointer type and vice versa TYPE(Link_Type), POINTER :: PEND TYPE Link_Ptr_TypeTYPE List_Type PRIVATE TYPE(Link_Type) :: Head ! Dummy Link always at head of listEND TYPE List_TypeCONTAINS!-----------------------------------------------------------------------SUBROUTINE Abort(Message)IMPLICIT NONECHARACTER *(*) MessageWRITE(6,*) MessageWRITE(6,*) 'Program aborted'STOPEND SUBROUTINE Abort!-----------------------------------------------------------------------SUBROUTINE LI_Check_List(List,Message)IMPLICIT NONETYPE(List_Type) ListCHARACTER *(*) MessageIF(.NOT.ASSOCIATED(List%Head%Next))THEN WRITE(6,*) Message CALL Abort('List is not initialised in call to LI_Check_List()')ENDIFEND SUBROUTINE LI_Check_List!-----------------------------------------------------------------------SUBROUTINE LI_Init_List(List) IMPLICIT NONE TYPE(List_Type),INTENT(INOUT),TARGET :: List NULLIFY(List%Head%Next) RETURNEND SUBROUTINE LI_Init_List!-----------------------------------------------------------------------SUBROUTINE LI_Add_To_Head(Link,List) IMPLICIT NONE TYPE(List_Type) ,INTENT(INOUT) :: List TYPE(Link_Ptr_Type),INTENT(INOUT) :: Link Link%P%Next => List%Head%Next List%Head%Next => Link%P RETURNEND SUBROUTINE LI_Add_To_Head!-----------------------------------------------------------------------INTEGER FUNCTION LI_Get_Len(List) IMPLICIT NONE TYPE(List_Type), INTENT(IN),TARGET :: LIST TYPE(Link_Ptr_Type) :: Link INTEGER N Link%P => List%Head N = 0 DO WHILE(ASSOCIATED(Link%P%Next)) Link%P => Link%P%Next N = N+1 ENDDO LI_Get_Len = N RETURNEND FUNCTION LI_Get_Len!-----------------------------------------------------------------------FUNCTION LI_Associated(Link) IMPLICIT NONE LOGICAL :: LI_Associated TYPE(Link_Ptr_Type),INTENT(IN) :: Link LI_Associated = .FALSE. IF(ASSOCIATED(Link%P))LI_Associated=.TRUE. RETURNEND FUNCTION LI_Associated!-----------------------------------------------------------------------subroutine LI_Nullify(Link) TYPE(Link_Ptr_Type),INTENT(OUT) :: Link nullify(Link%P) RETURNEND subroutine LI_Nullify!-----------------------------------------------------------------------FUNCTION LI_Get_Next(Link) IMPLICIT NONE Type(Link_Ptr_Type) :: LI_Get_Next TYPE(Link_Ptr_Type),INTENT(IN) :: Link IF(.NOT.ASSOCIATED(Link%P%Next))THEN NULLIFY(LI_Get_Next%P) ELSE LI_Get_Next%P => Link%P%Next ENDIF RETURNEND FUNCTION LI_Get_Next!-----------------------------------------------------------------------FUNCTION LI_Get_Head(List) IMPLICIT NONE TYPE(Link_Ptr_Type) :: LI_Get_Head TYPE(List_Type),INTENT(IN),TARGET :: List LI_Get_Head%P => List%Head%Next RETURNEND FUNCTION LI_Get_Head!-----------------------------------------------------------------------FUNCTION LI_Remove_Head(List) IMPLICIT NONE TYPE(Link_Ptr_Type) :: LI_Remove_Head TYPE(List_Type),INTENT(INOUT),TARGET :: List TYPE(Link_Ptr_Type) :: Link Link%P => List%Head%Next IF(ASSOCIATED(Link%P))THEN List%Head%Next => Link%P%Next NULLIFY(Link%P%Next) ENDIF LI_Remove_Head%P => Link%P RETURNEND FUNCTION LI_Remove_Head!-----------------------------------------------------------------------function LI_Remove_Next(Link,List) TYPE(Link_Ptr_Type) :: Link TYPE(List_Type),INTENT(INOUT),TARGET :: List TYPE(Link_Ptr_Type) :: Link_Dummy,LI_Remove_Next if (Associated(Link%P)) then Link_Dummy%P => Link%P%Next if (Associated(Link_Dummy%P)) then Link%P%Next => Link_Dummy%P%Next nullify(Link_Dummy%P%Next) endif LI_Remove_Next%P => Link_Dummy%P else LI_Remove_Next = LI_Remove_Head(List) endifend function LI_Remove_NextEND MODULE Generic_List
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -