Re: please try this program (generic resolution)



"James Van Buskirk" <not_valid@xxxxxxxxxxx> wrote in message
news:bpqdnfvMtKe7VGLanZ2dnUVZ_tuonZ2d@xxxxxxxxxxxxxx

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


.



Relevant Pages

  • Re: please try this program (generic resolution)
    ... "If the reference is consistent with a nonelemental reference to one ... of the specific interfaces of a generic interface that has that name and ... module procedure element, enisoc ... external fun ...
    (comp.lang.fortran)
  • Re: Optional function arguments, how?
    ... >> end interface ... > But that is quite ugly if I need to call fun several times with ... You cannot legally even reference an optional argument that is not ...
    (comp.lang.fortran)
  • Re: 7.0 wishlist?
    ... The "auto-implement" is intended mainly for the odd situation where an existing class you can't edit fits some interface and you're willing to take responsibility for it if it turns out not to actually adhere to the contract, and try using it where that interface type is expected. ... If reference declarations started showing up with the odd asterisk, bang, or other punctuation mark on it, but never primitive declarations, people would probably be able to guess what was going on, on the basis of "what other binary flag might be set on references but not primitives and would be really useful besides can be/cannot be null?" ... the compiler cannot prove by static analysis that the RHS isn't null might be a good idea. ... Object foo, bar; ...
    (comp.lang.java.programmer)
  • Re: Anders Hejlsberg comment on immutable objects
    ... >explicit interface implementation exists is so an interface name can class ... Improper implicit conversions constitute a nasty ... >> With value types, the variable's value is the object, not a reference ... Consider the affects of our different views on a const ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: C# Plugin system - same interface in two different assemblies...
    ... "add a reference to the appropriate assemblies to each and every project"? ... You don't have each plugin project deciding what ... its idea of the interface is. ... can't by forcing people to include them in assemblies as I've explained. ...
    (microsoft.public.dotnet.languages.csharp)

Loading