On Wed, 2017-07-19 at 12:09 +1200, John Harper wrote:
> A problem I have with kinds is that the three compilers I use most
> offer 4, 4 and 3 different real kinds: gfortran and g95 offer precisions
> 6,15,18,33 and ifort offers only 6,15,33. I have not yet discovered how
> to write a standard-conforming program, valid with all three compilers,
> that has a generic interface block and a specific function for each
> real kind. This little example showing what I mean works with gfortran
> and g95, but ifort complains, correctly, "Ambiguous generic interface
> SQR: previously declared specific procedure SQR18 is not distinguishable
> from this declaration. [SQR33]"
This was precisely the reason that I proposed that type aliases, which
were briefly on the table for 2008, should be replaced by a means to
define new types from old ones.
This was inspired by a simpler problem.
I had special function routines that were optimized for six and twelve
digits. So they had arguments and results with kind type parameters
SELECTED_REAL_KIND(6) and SELECTED_REAL_KIND(12). The generic worked
fine until I tried it with a processor that had only 64-bit real
arithmetic, where both were kinds for default real.
Something like
TYPE, NEW :: R6 => REAL(SELECTED_REAL_KIND(6)), &
R12 => REAL(SELECTED_REAL_KIND(12))
would define new types that do not have "free" kind type parameters, not
the same as default real or double precision. If we call them
extensions, dummy arguments of the base type would be type compatible
with actual arguments of those types, so things like SQRT and COS would
work, but generic resolution could tell the difference between R6 and
R12. For purposes of matching actual to dummy arguments, R6 and R12 are
still considered to have type parameters, just not free ones that can be
specified in type declaration statements, so objects of those types can
correspond to default real or double precision dummy arguments.
For a derived type A with two kind parameters named K1 and K2, something
like
TYPE, NEW :: NewA => A(K1=42)
would define NewA as a type with a "nonfree" kind type parameter named
K1 with the value 42, and "free" kind type parameter named K2 for which
a value can be specified in a type-declaration statement. With
TYPE(NewA(29)) :: X
TYPE(A(42,29)) :: Y
Y is type and kind compatible with X, but not vice versa.
> module sqrgeneric
> implicit none
> integer,parameter:: &
> k6 = selected_real_kind(6), k15 = selected_real_kind(15),&
> k18 = selected_real_kind(18),k33 = selected_real_kind(33)
> interface sqr
> module procedure sqr6,sqr15,sqr18,sqr33
> end interface sqr
> contains
> real(k6) function sqr6(x)
> real(k6),intent(in)::x
> sqr6 = x**2
> end function sqr6
>
> real(k15) function sqr15(x)
> real(k15),intent(in):: x
> sqr15 = x**2
> end function sqr15
>
> real(k18) function sqr18(x)
> real(k18),intent(in):: x
> sqr18 = x**2
> end function sqr18
>
> real(k33) function sqr33(x)
> real(k33),intent(in):: x
> sqr33 = x**2
> end function sqr33
> end module sqrgeneric
>
> program testit
> use sqrgeneric,only: k6,k15,k18,k33,sqr
> implicit none
> print *,sqr(2.0_k6),sqr(2.0_k15),sqr(2.0_k18),sqr(2.0_k33)
> end program testit
>
> -- John Harper, School of Mathematics and Statistics
> Victoria University, PO Box 600, Wellington 6140, New Zealand
> e-mail [log in to unmask] phone (+64)(4)463 5276 fax (+64)(4)463 5045
|