From: Tobias Burnus on
On 10/16/2009 07:01 AM, James Van Buskirk wrote:
> elemental function my_dcos(x)
> [...]
> call test(my_dcos)
> 1
> Error: ELEMENTAL non-INTRINSIC procedure 'my_dcos' is not allowed as an
> actual argument at (1)

That error is correct per:
"C1228 (R1221) A nonintrinsic elemental procedure shall not be used as
an actual argument." (F2003)
Same wording is in F2008 (C1233) and F95 (in Section 12.4).

(I find it interesting that NAG f95 allows it as "Extension: ...", I
always thought that it is an extremely strict compiler with almost no
legacy extensions. [ifort allows it a well (it prints a warning with
-stand f03).])


> So we can fix this:
>
> function my_dcos(x)
> [...]
> subroutine test(fun)
> interface
> elemental function fun(x)
>
> dcos.f90(33) : Error: The ELEMENTAL attribute of the associated actual
> procedure differs from the ELEMENTAL attribute of the dummy procedure. [MY_DCOS]

Even without looking at the standard, it makes sense that passing a
non-PURE, non-ELEMENTAL procedure to a PURE and ELEMENTAL dummy is not a
good idea.

The standard has (F2003, in 12.4.1.3 Actual arguments associated with
dummy procedure entities):

"If the interface of the dummy argument is explicit, the characteristics
listed in 12.2 shall be the same for the associated actual argument and
the corresponding dummy argument, except that a pure actual argument may
be associated with a dummy argument that is not pure and an elemental
intrinsic actual procedure may be associated with a dummy procedure"

Thus that "ifort" rejects it is OK. I filled a bug report (PR41724) for
gfortran which does not detect this.


> Now with DCOS, all this just works:
>
> C:\gfortran\clf\dcos>type dcos.f90
> subroutine test(fun)
> interface
> elemental function fun(x)
> [...]
> intrinsic dcos
> call test(dcos)

Is this actually valid or not? If I quote again from "12.4.1.3" but
include the trailing parentheses:

"an elemental intrinsic actual procedure may be associated with a dummy
procedure (which is prohibited from being elemental)."

The "which is prohibited" or as F2008 has it "(which cannot be
elemental).", implies that "interface; elemental function fun" is
already invalid.

Actually, I failed to find this restriction elsewhere in the standard.
As the parenthesis is normative, it should be enough, still - especially
the "cannot" somehow implies that this restriction is listed elsewhere
explicitly.

Tobias
From: James Van Buskirk on
"Tobias Burnus" <burnus(a)net-b.de> wrote in message
news:4AD8335E.2030401(a)net-b.de...

> On 10/16/2009 07:01 AM, James Van Buskirk wrote:

>> Now with DCOS, all this just works:

>> C:\gfortran\clf\dcos>type dcos.f90
>> subroutine test(fun)
>> interface
>> elemental function fun(x)
>> [...]
>> intrinsic dcos
>> call test(dcos)

> Is this actually valid or not? If I quote again from "12.4.1.3" but
> include the trailing parentheses:

> "an elemental intrinsic actual procedure may be associated with a dummy
> procedure (which is prohibited from being elemental)."

> The "which is prohibited" or as F2008 has it "(which cannot be
> elemental).", implies that "interface; elemental function fun" is
> already invalid.

> Actually, I failed to find this restriction elsewhere in the standard.
> As the parenthesis is normative, it should be enough, still - especially
> the "cannot" somehow implies that this restriction is listed elsewhere
> explicitly.

I read this as some sort of problem with the standard. At least it
says that it lets you pass DCOS as an actual argument without having
to declare the dummy argument as elemental, which would break codes
dating back to at least f77.

It could be that whoever wrote the quoted paragraph assumed that for
a dummy argument to be elemental was generally prohibited without
actually checking, or that the prohibition existed in a previous
draft but was dropped but not fixed in the quoted paragraph.

I can't see why the prohibition against passing a nonintrinsic
elemental procedure as an actual argument exists anyhow. It seems
to me that elemental procedures are deprecated at birth as a
result, and they seem more useful to me than to deserve such a
fate.

You know, there is a similar restriction regarding procedure
pointers:

C:\gfortran\clf\dcos>type ptr.f90
module funcs
implicit none
integer, parameter :: dp = kind(1.0d0)
abstract interface
elemental function fun(x)
import
implicit none
real(dp), intent(in) :: x
real(dp) fun
end function fun
end interface
contains
! function my_dcos(x)
elemental function my_dcos(x)
! integer :: dp = kind(1.0d0) !-- Or USE an appropriate module
integer, parameter :: dp = kind(1.0d0) !-- Or USE an appropriate module
real(dp), intent(in) :: x
real(dp) :: my_dcos
my_dcos = cos(x)
return
! end
end function
end module funcs

program start
use funcs
implicit none
procedure(fun), pointer :: f
real(dp) x(3)
! intrinsic dcos
x = [1,2,3]
f => my_dcos
! f => dcos
write(*,*) f(x)
end program start

C:\gfortran\clf\dcos>gfortran -Wall ptr.f90 -optr

C:\gfortran\clf\dcos>ptr
0.54030230586813976 -0.41614683654714241 -0.98999249660044542

Whoops, gfortran let this one slide!
OK, how about the other versions:

C:\gfortran\clf\dcos>type ptr.f90
module funcs
implicit none
integer, parameter :: dp = kind(1.0d0)
abstract interface
elemental function fun(x)
import
implicit none
real(dp), intent(in) :: x
real(dp) fun
end function fun
end interface
contains
function my_dcos(x)
! elemental function my_dcos(x)
! integer :: dp = kind(1.0d0) !-- Or USE an appropriate module
integer, parameter :: dp = kind(1.0d0) !-- Or USE an appropriate module
real(dp), intent(in) :: x
real(dp) :: my_dcos
my_dcos = cos(x)
return
! end
end function
end module funcs

program start
use funcs
implicit none
procedure(fun), pointer :: f
real(dp) x(3)
! intrinsic dcos
x = [1,2,3]
f => my_dcos
! f => dcos
write(*,*) f(x)
end program start

C:\gfortran\clf\dcos>gfortran -Wall ptr.f90 -optr

C:\gfortran\clf\dcos>ptr
0.54030230586813976 -0.41614683654714241 -0.98999249660044542

Now, we agree I think that gfortran should have caught that one as
we shouldn't be able to change non-elemental procedures to syntactically
elemental ones merely by pointing at them. The last version:

C:\gfortran\clf\dcos>type ptr.f90
module funcs
implicit none
integer, parameter :: dp = kind(1.0d0)
abstract interface
elemental function fun(x)
import
implicit none
real(dp), intent(in) :: x
real(dp) fun
end function fun
end interface
contains
function my_dcos(x)
! elemental function my_dcos(x)
! integer :: dp = kind(1.0d0) !-- Or USE an appropriate module
integer, parameter :: dp = kind(1.0d0) !-- Or USE an appropriate module
real(dp), intent(in) :: x
real(dp) :: my_dcos
my_dcos = cos(x)
return
! end
end function
end module funcs

program start
use funcs
implicit none
procedure(fun), pointer :: f
real(dp) x(3)
intrinsic dcos
x = [1,2,3]
! f => my_dcos
f => dcos
write(*,*) f(x)
end program start

C:\gfortran\clf\dcos>gfortran -Wall ptr.f90 -optr

C:\gfortran\clf\dcos>ptr
0.54030230586813976 -0.41614683654714241 -0.98999249660044542

Is there a parenthetical normative clause that appears to forbid this,
too?

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


From: Tobias Burnus on
On 16 October 2009 James Van Buskirk wrote:
> > I read this as some sort of problem with the standard. At least it
> > says that it lets you pass DCOS as an actual argument without having
> > to declare the dummy argument as elemental, which would break codes
> > dating back to at least f77.

It is not completely clear to me why there is/would be a problem.


> > It could be that whoever wrote the quoted paragraph assumed that for
> > a dummy argument to be elemental was generally prohibited without
> > actually checking, or that the prohibition existed in a previous
> > draft but was dropped but not fixed in the quoted paragraph.

Maybe - or I have simply missed to find the right spot.


> > I can't see why the prohibition against passing a nonintrinsic
> > elemental procedure as an actual argument exists anyhow.

Me neither; I think the way elemental procedures are commonly
implemented, it should just work - as ifort and NAG f95 show. (And
gfortran would likely show if the error check were removed.) However,
someone might have had a different implementation in mind
(hypothetically or really existing) were allowing would have lead to
problems.


> > You know, there is a similar restriction regarding procedure
> > pointers:
> >
> > abstract interface
> > elemental function fun(x)
> > [...]
> > elemental function my_dcos(x)
> > [...]
> > procedure(fun), pointer :: f
> > f => my_dcos
> > write(*,*) f(x)
> >
> > Whoops, gfortran let this one slide!

Actually, this program looks OK to me. Do you see anything in the
standard which does not allow this one? (Note, the proc-pointer is not
passed as actual argument but the procedure to which it is associated is
just called.)


> > OK, how about the other versions:
> >
> > abstract interface
> > elemental function fun(x)
> > [...]
> > function my_dcos(x)
> > [...]
> > procedure(fun), pointer :: f
> > f => my_dcos
> >
> > Now, we agree I think that gfortran should have caught that one as
> > we shouldn't be able to change non-elemental procedures to
> > syntactically elemental ones merely by pointing at them.

I agree that it is invalid and that gfortran should have caught it. (As
it is not a constraint, the compiler is not required to check this,
however.)

From the F2003 standard (7.4.2.2 Procedure pointer assignment)
"If proc-pointer-object has an explicit interface, its characteristics
shall be the same as proc-target except that proc-target may be pure
even if proc-pointer-object is not pure and proc-target may be an
elemental intrinsic procedure even if proc-pointer-object is not elemental."


> > The last version:
> >
> > abstract interface
> > elemental function fun(x)
> >
> > procedure(fun), pointer :: f
> > intrinsic dcos
> > f => dcos

Looks OK to me - assuming that "fun" has the same interface as "dcos"
(which seems to be the case). Again, you do not use the proc-pointer as
actual argument thus there should be no problem.

Tobias
From: Carlie Coats on
analyst41(a)hotmail.com wrote:
> (1) Using Double Precision for latitude and longitude and using double
> precision for degrees to radians and radius of the earth (by the way,
> I have seen values that differ by about 4 miles)
>
> (2) checking argument of acos to be between -1 and 1
>
> Seems to be working OK.
>
> Are the generic sin,cos and acos functions sufficient?
>
> Have functions such as DCOS become unnecessary in f95?
>
> Thanks for any responses.

Single precision arithmetic is normally not adequate for
geo-transformations (i.e.., except on a few platforms like
Cray vector machines).

The Earth is a spheroid, and modeling distances on it requires
elliptic integrals (something that I'd like to avoid, even though
I'm a mathematician myself). Not doing so can lead to errors on the
order of 12KM over distances of 3000 KM, according to an evaluation
I did myself a decade or so ago. (North American continental scale
meteorology plots had easily observable placement errors.)

If you want accurate terrestrial distances, you are better off either
using a package (e.g., "proj4" or "gctp") developed by by serious
geography-programmers, or doing the work "by hand" in a geographic
information system like GRASS.

FWIW -- Carlie Coats
From: Richard Maine on
Tobias Burnus <burnus(a)net-b.de> wrote:

> On 16 October 2009 James Van Buskirk wrote:
> > > I read this as some sort of problem with the standard. At least it
> > > says that it lets you pass DCOS as an actual argument without having
> > > to declare the dummy argument as elemental, which would break codes
> > > dating back to at least f77.
>
> It is not completely clear to me why there is/would be a problem.

I briefly wondered what this was saying also, but then I concluded that
it was probably just worded a bit hastily. I think he is saying that it
would break codes if it was not allowed to pass dcos as an actual
argument to a nonelemental dummy. That would certainly be true, insomuch
as it was allowed to pass dcos as an actual argument and... well... the
dummy arguments certainly were not elemental as there was no elemental
anything then.

> > > It could be that whoever wrote the quoted paragraph assumed that for
> > > a dummy argument to be elemental was generally prohibited without
> > > actually checking, or that the prohibition existed in a previous
> > > draft but was dropped but not fixed in the quoted paragraph.
>
> Maybe - or I have simply missed to find the right spot.

Yeah. I could have sworn there was such a prohibition, but I can't find
it in a quick skim. I can't say whether my skim missed the prohibition,
that parenthetical mention was intended to be the prohibition (which I'd
sure agree would be a strange way to express it), the prohibition was in
an earlier version of the standard as suggested above, or I am just
plain wrong in thinking there was such a prohibition.

Ah. Don't feel like looking further. It is still bugging me though.
Maybe eventually it will bug me enough that I'll go look a bit more
thoroughly (or maybe I'll get lucky and someone else will find it
first).

> > > I can't see why the prohibition against passing a nonintrinsic
> > > elemental procedure as an actual argument exists anyhow.
>
> Me neither; I think the way elemental procedures are commonly
> implemented, it should just work - as ifort and NAG f95 show. (And
> gfortran would likely show if the error check were removed.) However,
> someone might have had a different implementation in mind
> (hypothetically or really existing) were allowing would have lead to
> problems.

I do recall discussion of multiple possibilities for implementation of
elemental procedures. I don't recall the details, but I do recall that
bits of the standard were drafted so as to allow for multiple
possibilities. In particular, I was pretty sure that allowance for
various implementation strategies went into the restrictions on passing
elementals as arguments... the restrictions that I'm currently having
trouble finding. Seems to me that one set of possible implementation
differences involved whether an elemental procedure looked just like a
non-elemental one, with the calling procedure implicitly putting loops
around the scalar call, or whether the loops were inside of the called
procedure. To my knowledge and recollection (very much second hand, if
not third hand), most or all current compilers put the loops around the
call, but the standard was supposed to accomodate either approach.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain