blob: 2472603db41455969b57dcf40b7c91dcbb47add3 [file] [log] [blame]
! { dg-do run }
!
! Third, complete example from the PGInsider article:
! "Object-Oriented Programming in Fortran 2003 Part 3: Parameterized Derived Types"
! by Mark Leair
!
! Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
!
! NVIDIA CORPORATION and its licensors retain all intellectual property
! and proprietary rights in and to this software, related documentation
! and any modifications thereto. Any use, reproduction, disclosure or
! distribution of this software and related documentation without an express
! license agreement from NVIDIA CORPORATION is strictly prohibited.
!
! THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT
! WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT
! NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR
! FITNESS FOR A PARTICULAR PURPOSE.
!
! Note that modification had to be made all of which are commented.
!
module matrix
type :: base_matrix(k,c,r)
private
integer, kind :: k = 4
integer, len :: c = 1
integer, len :: r = 1
end type base_matrix
type, extends(base_matrix) :: adj_matrix
private
class(*), pointer :: m(:,:) => null()
end type adj_matrix
interface getKind
module procedure getKind4
module procedure getKind8
end interface getKind
interface getColumns
module procedure getNumCols4
module procedure getNumCols8
end interface getColumns
interface getRows
module procedure getNumRows4
module procedure getNumRows8
end interface getRows
interface adj_matrix
module procedure construct_4 ! kind=4 constructor
module procedure construct_8 ! kind=8 constructor
end interface adj_matrix
interface assignment(=)
module procedure m2m4 ! assign kind=4 matrix
module procedure a2m4 ! assign kind=4 array
module procedure m2m8 ! assign kind=8 matrix
module procedure a2m8 ! assign kind=8 array
module procedure m2a4 ! assign kind=4 matrix to array
module procedure m2a8 ! assign kind=8 matrix to array
end interface assignment(=)
contains
function getKind4(this) result(rslt)
class(adj_matrix(4,*,*)) :: this
integer :: rslt
rslt = this%k
end function getKind4
function getKind8(this) result(rslt)
class(adj_matrix(8,*,*)) :: this
integer :: rslt
rslt = this%k
end function getKind8
function getNumCols4(this) result(rslt)
class(adj_matrix(4,*,*)) :: this
integer :: rslt
rslt = this%c
end function getNumCols4
function getNumCols8(this) result(rslt)
class(adj_matrix(8,*,*)) :: this
integer :: rslt
rslt = this%c
end function getNumCols8
function getNumRows4(this) result(rslt)
class(adj_matrix(4,*,*)) :: this
integer :: rslt
rslt = this%r
end function getNumRows4
function getNumRows8(this) result(rslt)
class(adj_matrix(8,*,*)) :: this
integer :: rslt
rslt = this%r
end function getNumRows8
function construct_4(k,c,r) result(mat)
integer(4) :: k
integer :: c
integer :: r
class(adj_matrix(4,:,:)),allocatable :: mat
allocate(adj_matrix(4,c,r)::mat)
end function construct_4
function construct_8(k,c,r) result(mat)
integer(8) :: k
integer :: c
integer :: r
class(adj_matrix(8,:,:)),allocatable :: mat
allocate(adj_matrix(8,c,r)::mat)
end function construct_8
subroutine a2m4(d,s)
class(adj_matrix(4,:,:)),allocatable :: d
class(*),dimension(:,:) :: s
if (allocated(d)) deallocate(d)
! allocate(adj_matrix(4,size(s,1),size(s,2))::d) ! generates assembler error
allocate(d, mold = adj_matrix(4,size(s,1),size(s,2)))
allocate(d%m(size(s,1),size(s,2)),source=s)
end subroutine a2m4
subroutine a2m8(d,s)
class(adj_matrix(8,:,:)),allocatable :: d
class(*),dimension(:,:) :: s
if (allocated(d)) deallocate(d)
! allocate(adj_matrix(8,size(s,1),size(s,2))::d) ! generates assembler error
allocate(d, mold = adj_matrix(8_8,size(s,1),size(s,2))) ! Needs 8_8 to match arg1 of 'construct_8'
allocate(d%m(size(s,1),size(s,2)),source=s)
end subroutine a2m8
subroutine m2a8(a,this)
class(adj_matrix(8,*,*)), intent(in) :: this ! Intents required for
real(8),allocatable, intent(out) :: a(:,:) ! defined assignment
select type (array => this%m) ! Added SELECT TYPE because...
type is (real(8))
if (allocated(a)) deallocate(a)
allocate(a,source=array)
end select
! allocate(a(size(this%m,1),size(this%m,2)),source=this%m) ! ...CLASS(*) source does not work in gfortran
end subroutine m2a8
subroutine m2a4(a,this)
class(adj_matrix(4,*,*)), intent(in) :: this ! Intents required for
real(4),allocatable, intent(out) :: a(:,:) ! defined assignment
select type (array => this%m) ! Added SELECT TYPE because...
type is (real(4))
if (allocated(a)) deallocate(a)
allocate(a,source=array)
end select
! allocate(a(size(this%m,1),size(this%m,2)),source=this%m) ! ...CLASS(*) source does not work in gfortran
end subroutine m2a4
subroutine m2m4(d,s)
CLASS(adj_matrix(4,:,:)),allocatable, intent(OUT) :: d ! Intents required for
CLASS(adj_matrix(4,*,*)), intent(in) :: s ! defined assignment
if (allocated(d)) deallocate(d)
allocate(d,source=s)
end subroutine m2m4
subroutine m2m8(d,s)
CLASS(adj_matrix(8,:,:)),allocatable, intent(OUT) :: d ! Intents required for
CLASS(adj_matrix(8,*,*)), intent(in) :: s ! defined assignment
if (allocated(d)) deallocate(d)
allocate(d,source=s)
end subroutine m2m8
end module matrix
program adj3
use matrix
implicit none
integer(8) :: i
class(adj_matrix(8,:,:)),allocatable :: adj ! Was TYPE: Fails in
real(8) :: a(2,3) ! defined assignment
real(8),allocatable :: b(:,:)
class(adj_matrix(4,:,:)),allocatable :: adj_4 ! Ditto and ....
real(4) :: a_4(3,2) ! ... these declarations were
real(4),allocatable :: b_4(:,:) ! added to check KIND=4
! Check constructor of PDT and instrinsic assignment
adj = adj_matrix(INT(8,8),2,4)
if (adj%k .ne. 8) STOP 1
if (adj%c .ne. 2) STOP 2
if (adj%r .ne. 4) STOP 3
a = reshape ([(i, i = 1, 6)], [2,3])
adj = a
b = adj
if (any (b .ne. a)) STOP 4
! Check allocation with MOLD of PDT. Note that only KIND parameters set.
allocate (adj_4, mold = adj_matrix(4,3,2)) ! Added check of KIND = 4
if (adj_4%k .ne. 4) STOP 5
a_4 = reshape (a, [3,2])
adj_4 = a_4
b_4 = adj_4
if (any (b_4 .ne. a_4)) STOP 6
end program adj3