From: James Van Buskirk on
"James Van Buskirk" <not_valid(a)comcast.net> wrote in message
news:bpqdnfvMtKe7VGLanZ2dnUVZ_tuonZ2d(a)comcast.com...

I have heard that it's bad manners to follow-up to your own post
but I was hoping in vain that someone else would correct my
errors.

> I'm not sure that I catch the meaning of this paragraph. After all, it's
> commonplace to have a fixed-rank specific procedure that has the same
> generic name as the corresponding elemental procedure. That feature is
> there because it may be desirable to write out a highly-optimized
> procedure for a given rank, but also to hedge ones bets by providing an
> elemental procedure that would otherwise cover the optimize case.

I still think it's correct up to here.

> In
> reading 12.4.4.1 of N1601.pdf:

> "(1) If the reference is consistent with a nonelemental reference to one
> of the specific interfaces of a generic interface that has that name and
> either is in the scoping unit in which the reference appears or is made
> accessible by a USE statement in the scoping unit, the reference is to
> the specific procedtre in the interface block that provides that
> interface. The rules in 16.2.3 ensure that there can be at most one
> such specific procedure.
> (2) If (1) does not apply, if the reference is consistent with an
> elemental reference to one of the specific interfaces of a generic
> interface that has that name and either is in the scoping unit in which
> the reference appears or is made accessible by a USE statement in the
> scoping unit, the reference is to the specific elemental procedure in
> the interface block that provides that interface. The rules in 16.2.3
> ensure that there can be at most one such specific elemental procedure."

> This is saying that nonelemental procedures trump elemental ones. The
> compiler is supposed to compare all the nonelemental procedures first
> and use one of those if it matches, and only if no nonelemental
> procedure works, then shuffle through the list of elemental procedures
> to see if one of them works.

I didn't notice in the above that the standard isn't really saying this.
There are two ways this way of thinking conflicts with the standard:

1) The standard says that nonelemental REFERENCES trump elemental
REFERENCES. A reference to an elemental procedure with all scalar
actual arguments is not an elemental reference, see N1601.pdf, section
12.4.2:

"A reference to an elemental function (12.7) is an elemental reference
if one or more actual arguments are arrays and all array arguments
have the same shape."

Similar verbiage exists in section 12.4.3 for subroutines.

2) The standard does not say that elemental references always trump
nonelemental references. Host-associated names go to the back of the
bus in such a way that they can be blocked by other names. Thanks to
Bob Corbett who pointed this out with clarity in

http://groups.google.com/group/comp.lang.fortran/msg/3ca1c4732c6909e6

> If elemental procedures conflicted with
> elemental procedures in the fashion suggested, why would there be a
> need to separate parts (1) and (2) above instead of just making them
> into one big part (1) where no distinction was made between elemental
> and nonelemental procedures?

> Here is an example:

> C:\gfortran\clf\cos_test>ifort /stand:f03 ex1.f90

> pure function enisoc(x)
> --------------------^
> ex1.f90(28) : Error: This name does not have a type, and must have an
> explicit t
> ype. [ENICOS]
> print *, enicos(1.0)
> ------------^
> compilation aborted for ex1.f90 (code 1)

And now in my example I misspelled ENISOC. Just shows how a bad
choice of variable names can make a program unreadable and
untypable. Fixing up my example:

C:\gfortran\clf\cos_test>type ex1a.f90
module cos_mod
implicit none
interface enisoc
module procedure element, enisoc
end interface enisoc
contains
pure function enisoc(x)
real, intent(in) :: x
real enisoc

enisoc = 2
end function enisoc

elemental function element(x)
real, intent(in) :: x
real element

element = cos(x)
end function element
end module cos_mod

program main
use cos_mod
implicit none
real fun
external fun

print *, enisoc(0.0)
print *, enisoc([0.0])
print *, fun(enisoc, 0.0)
end program main

function fun(f,x)
implicit none
real fun
real f
real x

fun = f(x)
end function fun

C:\gfortran\clf\cos_test>c:\gcc_equation\bin\x86_64-pc-mingw32-gfortran -std=f20
03 ex1a.f90 -oex1a
ex1a.f90:4.38:

module procedure element, enisoc
1
Error: Ambiguous interfaces 'enisoc' and 'element' in generic interface
'enisoc'
at (1)
ex1a.f90:23.14:

use cos_mod
1
Fatal Error: Can't open module file 'cos_mod.mod' for reading at (1): No
such fi
le or directory
x86_64-pc-mingw32-gfortran: Internal error: Aborted (program f951)
Please submit a full bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.

C:\gfortran\clf\cos_test>ifort /stand:f03 ex1a.f90
Intel(R) Fortran Compiler for Intel(R) EM64T-based applications, Version 9.1
Build 20061104
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

ex1a.f90(7) : Warning: The type/rank/keyword signature for this specific
procedu
re matches another specific procedure that shares the same generic-name.
[ENIS
OC]
pure function enisoc(x)
--------------------^
Microsoft (R) Incremental Linker Version 8.00.40310.39
Copyright (C) Microsoft Corporation. All rights reserved.

-out:ex1a.exe
-subsystem:console
ex1a.obj

C:\gfortran\clf\cos_test>ex1a
2.000000
1.000000
2.000000

So gfortran rejects it and ifort accepts it. Which is right?
Well, according to the literal words of the standard I think
they both are. As stated above, although procedures that accept
array arguments can override elemental procedures, procedures
that have only scalar arguments can't because a conflicting
reference to the elemental proceedure would not be an elemental
reference. Quirk of the standard as I see it, but it's what the
standard says. Thus gfortran rejects it and ifort accepts it
with a warning and does perform the override as desired. ifort
should insert the keywords "QUIRK IN STANDARD" in their warning
message, though :)

Now for a fixed-up version of this example that does perform
the override as in Note 12.34:

C:\gfortran\clf\cos_test>type ex1b.f90
module cos_mod
implicit none
interface enisoc
module procedure element, enisoc
end interface enisoc
contains
pure function enisoc(x)
real, intent(in) :: x(:)
real enisoc(size(x))

enisoc = 2
end function enisoc

elemental function element(x)
real, intent(in) :: x
real element

element = cos(x)
end function element
end module cos_mod

program main
use cos_mod
implicit none
! real fun ! gfortran should reject if this line uncommented
interface
function fun(f,x)
implicit none
interface
pure function f(x)
real, intent(in) :: x(:)
real f(size(x))
end function f
end interface
real x(:)
! real fun(size(f(x))) ! ICE with ifort if this line in force
real fun(size(x)) ! ifort handles this OK
end function fun
end interface

print *, enisoc(0.0)
print *, enisoc([0.0])
print *, fun(enisoc, [0.0])
end program main

function fun(f,x)
implicit none
interface
pure function f(x)
real, intent(in) :: x(:)
real f(size(x))
end function f
end interface
real x(:)
real fun(size(f(x)))

fun = f(x)
end function fun

C:\gfortran\clf\cos_test>c:\gcc_equation\bin\x86_64-pc-mingw32-gfortran -std=f20
03 ex1b.f90 -oex1b

C:\gfortran\clf\cos_test>ex1b
1.00000000
2.0000000
2.0000000

C:\gfortran\clf\cos_test>ifort /stand:f03 ex1b.f90
Intel(R) Fortran Compiler for Intel(R) EM64T-based applications, Version 9.1
Build 20061104
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 8.00.40310.39
Copyright (C) Microsoft Corporation. All rights reserved.

-out:ex1b.exe
-subsystem:console
ex1b.obj

C:\gfortran\clf\cos_test>ex1b
1.000000
2.000000
2.000000

So the example works, and even better it exposes a couple of errors
in gfortran and ifort as noted in the comments.

Now I think I begin to understand what the thread is about: a name
can refer to multiple things, such as a generic name, a specific
procedure name, and an intrinsic procedure name, and the standard
permits names of perhaps unrelated things to block host-associated
names in a perhaps quirky, nonintuitive and surprising fashion.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


First  |  Prev  | 
Pages: 1 2 3 4
Prev: Good book on FORTRAN OT
Next: branch prediction?