news:98b18872-8023-4afb...@googlegroups.com...
A virus has prevented me from participating in this thread until
now. It seem to me that for the INCLUDE method, which attempts
to mimic C++ templates, you only need 2 procedures written out:
C:\gfortran\clf\vec_template>type templates.i90
elemental function scalar_times_vec(Qscalar, vector)
type(vec) scalar_times_vec
type(vec), intent(in) :: vector
intent(in) :: Qscalar
type(vec) vec_times_scalar
entry vec_times_scalar(vector, Qscalar)
scalar_times_vec = vec( &
x = Qscalar*vector%x, &
y = Qscalar*vector%y, &
z = Qscalar*vector%z)
end function scalar_times_vec
C:\gfortran\clf\vec_template>type vec_template.f90
module mykinds
implicit none
integer, parameter :: R4P = selected_real_kind(6,30)
integer, parameter :: R8P = selected_real_kind(15,300)
integer, parameter :: I1P = selected_int_kind(2)
integer, parameter :: I2P = selected_int_kind(4)
integer, parameter :: I4P = selected_int_kind(9)
integer, parameter :: I8P = selected_int_kind(18)
end module mykinds
module vec_def
use mykinds
implicit none
private
type, public :: vec
real(R8P) x
real(R8P) y
real(R8P) z
end type vec
end module vec_def
module vec_template
use vec_def
implicit none
private
public operator(*)
interface operator(*)
module procedure cross
end interface operator(*)
contains
elemental function cross(x,y)
type(vec) cross
type(vec), intent(in) :: x
type(vec), intent(in) :: y
cross = vec( &
x = x%y*y%z-x%z*y%y, &
y = x%z*y%x-x%x*y%z, &
z = x%x*y%y-x%y*y%x)
end function cross
end module vec_template
module R4P_template
use mykinds
use vec_def
implicit real(R4P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module R4P_template
module R8P_template
use mykinds
use vec_def
implicit real(R8P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module R8P_template
module I1P_template
use mykinds
use vec_def
implicit integer(I1P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module I1p_template
module I2P_template
use mykinds
use vec_def
implicit integer(I2P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module I2p_template
module I4P_template
use mykinds
use vec_def
implicit integer(I4P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module I4p_template
module I8P_template
use mykinds
use vec_def
implicit integer(I8P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module I8p_template
module vec_mod
use vec_def
use vec_template
use R4P_template
use R8P_template
use I1P_template
use I2P_template
use I4P_template
use I8P_template
end module vec_mod
program test
use mykinds
use vec_mod
implicit none
type(vec) a, b
real(R4P) x4
real(R8P) x8
integer(I1P) i1
integer(I2P) i2
integer(I4P) i4
integer(I8P) i8
a = vec(1, 2, 3)
b = vec(2, 3, 4)
x4 = 2
x8 = 3
i1 = 4
i2 = 5
i4 = 6
i8 = 7
write(*,*) a*b
write(*,*) x8*b
write(*,*) x4*b
write(*,*) i8*b
write(*,*) i4*b
write(*,*) i2*b
write(*,*) i1*b
write(*,*) a*x8
write(*,*) a*x4
write(*,*) a*i8
write(*,*) a*i4
write(*,*) a*i2
write(*,*) a*i1
end program test
C:\gfortran\clf\vec_template>gfortran vec_template.f90 -ovec_template
vec_template.f90:132.12:
program test
1
Error: Name 'scalar_times_vec' at (1) is an ambiguous reference to
'scalar_times
_vec' from module 'r4p_template'
vec_template.f90:132.12:
program test
1
Internal Error at (1):
Unable to find symbol scalar_times_vec
I think the error above is in gfortran; my code looks OK.
Note that there are several refinements that have been
suggested by other posters to the INCLUDE method such as
using implicit typing to permit both integer and real types
to be used in the template code and ENTRY statements for
commutative operators, and not publishing the specific
names.
The implicit typing has limitations and could be avoided
if compilers implemented syntax like:
module m1
integer, parameter, private :: dp = kind(1.0d0)
type(real(dp)), parameter, private :: xdp = 0
end module m1
module m2
use m1, only: template_type => real(dp)
type(template_type) x
end module m2
but I don't know if the above is standard conforming and neither
ifort nor gfortran allow it. It's a pity that one can clone
procedures like:
procedure(any_old_procedure) template_procedure
but not types like:
variable(any_old_variable) template_variable
The former standard usage seems much more complicated than the latter
nonstandard one because not only does the compliler have to pass on
the return type of function any_old_procedure, but also the
characteristics of its arguments and the hidden procedure that
processes the specification-part of any_old_procedure so that
the calling program can know the shape and any length type
parameters of its result variable. Of course some may consider
specification statements such as:
variable(any_old_variable), parameter :: one = 1
to be confusing, but it's no worse than some other terminology in
the Fortran language definition.
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end