! Associative map string -> real(8) module amap implicit none ! The key type key_t private character(len=16) :: k = '-' contains procedure, private :: equals_key_t generic, public :: operator(==) => equals_key_t procedure, private :: write_key_t generic, public :: write(formatted) => write_key_t procedure, private :: set_to_key_t generic, public :: assignment(=) => set_to_key_t end type key_t ! The value type value_t private real(8) :: v = huge(0.0d0) ! An out-of-band value contains procedure, private :: write_value_t generic, public :: write(formatted) => write_value_t procedure, private :: set_to_value_t generic, public :: assignment(=) => set_to_value_t end type value_t ! Map elements are (key,value) pairs type pair_t type(key_t) :: k = key_t() type(value_t) :: v = value_t() end type pair_t ! The map type amap_t private type(pair_t), allocatable :: pairs(:) integer, private :: extent = 10 integer, private :: high_water = 0 contains procedure, public :: get => get_amap_t procedure, public :: get_value => get_value_amap_t procedure, public :: set => set_amap_t procedure, public :: find => find_amap_t procedure, public :: print => print_amap_t procedure, public :: clear => clear_amap_t procedure, private :: is_key_kt procedure, private :: is_key_kvt generic, public :: contains => is_key_kt, is_key_kvt end type amap_t contains subroutine clear_amap_t(this) class(amap_t), intent(inout) :: this if (allocated(this%pairs)) then deallocate(this%pairs) end if this%high_water = 0 end subroutine clear_amap_t subroutine set_to_key_t(this, k) class(key_t), intent(inout) :: this character(len=*), intent(in) :: k this%k = adjustl(k) end subroutine set_to_key_t subroutine set_to_value_t(this, v) class(value_t), intent(inout) :: this real(8), intent(in) :: v this%v = v end subroutine set_to_value_t subroutine print_amap_t(this) class(amap_t), intent(in) :: this integer :: i write(6,'(a,i0,a)') 'Map has ',this%high_water,' elements' do i=1,this%high_water write(6,'(4x,dt,a,dt)') this%pairs(i)%k,' -> ',this%pairs(i)%v end do end subroutine print_amap_t subroutine set_amap_t(this,kv,vv) class(amap_t), intent(inout) :: this character(len=*), intent(in) :: kv real(8), intent(in) :: vv type(pair_t), allocatable :: tmp_pairs(:) type(key_t) :: k type(value_t) :: v integer :: idx k = kv v = vv if (.not. allocated(this%pairs)) then allocate(this%pairs(this%extent)) end if idx = this%find(k) if (idx > 0) then this%pairs(idx) = pair_t(k,v) return end if if (this%high_water == size(this%pairs)) then allocate(tmp_pairs(size(this%pairs)+this%extent)) tmp_pairs(1:this%high_water) = this%pairs call move_alloc(tmp_pairs, this%pairs) end if this%high_water = this%high_water + 1 this%pairs(this%high_water) = pair_t(k,v) end subroutine set_amap_t function find_amap_t(this, k) result(r) class(amap_t), intent(in) :: this type(key_t), intent(in) :: k integer :: r do r = 1, this%high_water if (this%pairs(r)%k == k) then return end if end do r = 0 end function find_amap_t function get_amap_t(this, kv) result(r) class(amap_t), intent(in) :: this character(len=*), intent(in) :: kv type(value_t) :: r type(key_t) :: k integer :: idx k = kv idx = this%find(k) if (idx > 0) then r = this%pairs(idx)%v else r = value_t() end if end function get_amap_t function get_value_amap_t(this, kv) result(r) class(amap_t), intent(in) :: this character(len=*), intent(in) :: kv real(8) :: r type(value_t) :: s s = this%get(kv) r = s%v end function get_value_amap_t function is_key_kt(this, k) result(r) class(amap_t), intent(in) :: this type(key_t), intent(in) :: k logical :: r r = this%find(k) > 0 end function is_key_kt function is_key_kvt(this, kv) result(r) class(amap_t), intent(in) :: this character(len=*), intent(in) :: kv logical :: r r = this%find(key_t(kv)) > 0 end function is_key_kvt function equals_key_t(this, k) result(r) class(key_t), intent(in) :: this type(key_t), intent(in) :: k logical :: r r = trim(adjustl(this%k)) == trim(adjustl(k%k)) end function equals_key_t subroutine write_key_t(key, unit, iotype, v_list, iostat, iomsg) class(key_t), intent(in) :: key integer, intent(in) :: unit character(*), intent(in) :: iotype integer, intent(in) :: v_list(:) integer, intent(out) :: iostat character(*), intent(inout) :: iomsg iostat = 0 !iomsg = "" write(6,'(a)', iostat=iostat, iomsg=iomsg) trim(adjustl(key%k)) end subroutine write_key_t subroutine write_value_t(value, unit, iotype, v_list, iostat, iomsg) class(value_t), intent(in) :: value integer, intent(in) :: unit character(*), intent(in) :: iotype integer, intent(in) :: v_list(:) integer, intent(out) :: iostat character(*), intent(inout) :: iomsg iostat = 0 !iomsg = "" write(6,'(f0.6)', iostat=iostat, iomsg=iomsg) value%v end subroutine write_value_t end module amap