Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Intrinsic function for dp vs sp?

113 views
Skip to first unread message

jski

unread,
Sep 10, 2012, 11:09:47 PM9/10/12
to
Searching on the web I found some sites that show cos() for sp and
dcos() for dp. The GNU Fortran site seems to indicate that dcos() is
deprecated ("archaic")? Are there different calls for sp vs. dp for
the intrinsic functions?

---John

glen herrmannsfeldt

unread,
Sep 10, 2012, 11:52:32 PM9/10/12
to
The old calls are still there, but for the usual uses the compiler
figures out the right one from the type of the operand.

One case where it still matters is using a function name as an
actual argument, such as to a numerical integration routine.
Since it is rare to need to numerically integrate cos(), you can
probably forget about that one.

-- glen

Steven G. Kargl

unread,
Sep 11, 2012, 12:45:49 AM9/11/12
to
Can you provide a URL to where the gfortran site says that DCOS
is archaic?

Please see any Fortran tutorial or reference that discussion
"generic" and "specific" intrinsic procedures.

--
steve

Wolfgang Kilian

unread,
Sep 11, 2012, 2:38:44 AM9/11/12
to
For writing new code, simply forget about dcos, dsqrt, ... They were
needed, except in very specific and rare context, only before FORTRAN
77. You will see them a lot in old and even some current code, however,
because many programmers don't learn the language from scratch but by
looking at even older code.

-- Wolfgang

--
E-mail: firstnameini...@domain.de
Domain: yahoo

jski

unread,
Sep 11, 2012, 3:19:01 AM9/11/12
to
On Sep 11, 12:45 am, "Steven G. Kargl"
http://gcc.gnu.org/onlinedocs/gcc-3.4.3/g77/DCos-Intrinsic.html#DCos-Intrinsic

8.11.9.68 DCos Intrinsic

DCos(X)

DCos: REAL(KIND=2) function.

X: REAL(KIND=2); scalar; INTENT(IN).

Intrinsic groups: (standard FORTRAN 77).

Description:

Archaic form of COS() that is specific to one type for X. See Cos
Intrinsic.

Tobias Burnus

unread,
Sep 11, 2012, 3:52:21 AM9/11/12
to
On 09/11/2012 09:19 AM, jski wrote:
>>> GNU Fortran site

Regarding GNU Fortran: There are two compilers under this name: g77 and
gfortran [or three if one counts g95]. g77 was part of GCC in the 3.x
versions - and you quote its documentation at

> http://gcc.gnu.org/onlinedocs/gcc-3.4.3/g77/DCos-Intrinsic.html#DCos-Intrinsic

Since GCC 4.x it has been replaced by gfortran, which besides Fortran 77
also supports Fortran 90/95 and to some extent Fortran 2003 and 2008. As
gfortran supports nearly all g77 features, there should be no reason to
use g77 - also not for pure Fortran 77 code.

gfortran's COS documentation is at
http://gcc.gnu.org/onlinedocs/gfortran/COS.html (or go to
http://gcc.gnu.org/onlinedocs/and pick the doucmentation for your
version of GCC).

On that page, a better distinction between COS as generic procedure name
and the specific names COS/DCOS/CCOS (and as GNU extension) ZCOD/CDCOS
is made.

As others have written, except of very few cases, you should use COS
with real or complex expression, independent of its kind (single, double
etc. precision).

Tobias

glen herrmannsfeldt

unread,
Sep 11, 2012, 11:46:50 AM9/11/12
to
jski <john.chl...@gmail.com> wrote:
(snip)

> http://gcc.gnu.org/onlinedocs/gcc-3.4.3/g77/DCos-Intrinsic.html#DCos-Intrinsic

> 8.11.9.68 DCos Intrinsic
> DCos(X)
> DCos: REAL(KIND=2) function.
> X: REAL(KIND=2); scalar; INTENT(IN).

> Intrinsic groups: (standard FORTRAN 77).
> Description:
> Archaic form of COS() that is specific to one type for X. See Cos
> Intrinsic.

The standard has it under

"Specific names for standard intrinsic functions"

Doesn't say anything about archaic.

There is very little reason to use it, but it is still standard.

-- glen

Richard Maine

unread,
Sep 11, 2012, 12:17:49 PM9/11/12
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> The standard has it under
>
> "Specific names for standard intrinsic functions"
>
> Doesn't say anything about archaic.
>
> There is very little reason to use it, but it is still standard.

Likely the only reason the standard doesn't say it is archaic is because
the standard doesn't say such things at all. There was a category of
deprecated features once proposed for f90, but it got dropped as too
controversial.

Any recommendation about whether something should be avoided as archaic
(or deprecated if one prefers that term) is a personal one rather than
one in the standard. Just because the standard doesn't have such
recommendations doesn't mean they can't be darned good ideas.

I personally consider things like DCOS to be archaic, and I recommend
never using it. I'm not going to waffle by saying "rarely". I mean that
"never" literally. Yes, I know you can invent a case where one could use
it. But such things are so rare that I do not recall ever once seeing
such a case in code "in the wild", as opposed to code where people are
trying to illustrate how it might be used. I supose my recollection
could be faulty, but again I mean that "not once" literally.

That puts it in the category of things whose utility is so low that I
believe one is better off ignoring completely. If you do happen to know
about the feature, pretend that you don't anyway. The only times you
even need to know that the feature exists is when you are reading old
codes.... or when you are explaining to someone why they should be
ignoring the feature.

If there ever actually was a reason to pass a specific intrinsic as an
actual argument in real production, I'd wrap the generic version in my
own specific rather than use the standard one.

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

glen herrmannsfeldt

unread,
Sep 11, 2012, 12:43:07 PM9/11/12
to
Richard Maine <nos...@see.signature> wrote:

(snip, I wrote)
>> The standard has it under

>> "Specific names for standard intrinsic functions"

>> Doesn't say anything about archaic.

(snip)

> Likely the only reason the standard doesn't say it is archaic is because
> the standard doesn't say such things at all. There was a category of
> deprecated features once proposed for f90, but it got dropped as too
> controversial.

There is still a note in F2008 on the small typeface for depracated
features. I don't know that there are actually any with that typeface.

As far as I can tell, the specific names section doesn't use the
depracated typeface.

> Any recommendation about whether something should be avoided as archaic
> (or deprecated if one prefers that term) is a personal one rather than
> one in the standard. Just because the standard doesn't have such
> recommendations doesn't mean they can't be darned good ideas.

Still, compiler documentation is different from ones personal
opinion in a newsgroup post.

> I personally consider things like DCOS to be archaic, and I recommend
> never using it. I'm not going to waffle by saying "rarely". I mean that
> "never" literally. Yes, I know you can invent a case where one could use
> it. But such things are so rare that I do not recall ever once seeing
> such a case in code "in the wild", as opposed to code where people are
> trying to illustrate how it might be used. I supose my recollection
> could be faulty, but again I mean that "not once" literally.

Yes. The need for numerically integrating cos() should be pretty
small. I can imagine it in a test program, maybe testing a numerical
integration routine. I suppose I could even imagine adding it to
a test suite for an integration or minimization routine.

> That puts it in the category of things whose utility is so low that I
> believe one is better off ignoring completely. If you do happen to know
> about the feature, pretend that you don't anyway. The only times you
> even need to know that the feature exists is when you are reading old
> codes.... or when you are explaining to someone why they should be
> ignoring the feature.

Not only is it still in the standard, but the bullet to indicate
which functions can't be used as actual arguments is still there.
(Cos doesn't have one.)

> If there ever actually was a reason to pass a specific intrinsic as an
> actual argument in real production, I'd wrap the generic version in my
> own specific rather than use the standard one.

For real production, I agree. For a test program, and maybe for a
quality verification program, I might actually use it. (See how close
the numeric integral comes to the analytic value.)

-- glen

Richard Maine

unread,
Sep 11, 2012, 2:01:42 PM9/11/12
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> There is still a note in F2008 on the small typeface for depracated
> features.

Not worth my bothering to check, but I seriously doubt it. You are
probably talking about obsolescent features instead of deprecated ones.
Those are not the same thing.

Obsolescence is defined in the standard. It is supposed to be for
features that are not widely used and are likely candidates for future
deletion. I'd personally have put things like DCOS on that list, but the
standard doesn't.

Deprecated features, as proposed in early drafts of f90, were ones not
yet qualifying for the obsolescent tag. Some of the fetaures proposed as
deprecated were *VERY* widely used, as in it was hard to find a program
of significant size that didn't use them extensively. For example,
COMMON was on the list. That whole concept got dropped from the standard
as just too controversial to agree on the details.

James Van Buskirk

unread,
Sep 11, 2012, 2:19:07 PM9/11/12
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1kq927s.5sh2zyx1fkk8N%nos...@see.signature...

> If there ever actually was a reason to pass a specific intrinsic as an
> actual argument in real production, I'd wrap the generic version in my
> own specific rather than use the standard one.

But suppose I wanted to declare a procedure pointer to a function
that took one double-precision argument with keyword X= and returned
a double-precision result?

procedure(DCOS), pointer :: p1

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


Richard Maine

unread,
Sep 11, 2012, 2:55:48 PM9/11/12
to
James Van Buskirk <not_...@comcast.net> wrote:

> "Richard Maine" <nos...@see.signature> wrote in message
> news:1kq927s.5sh2zyx1fkk8N%nos...@see.signature...
>
> > If there ever actually was a reason to pass a specific intrinsic as an
> > actual argument in real production, I'd wrap the generic version in my
> > own specific rather than use the standard one.
>
> But suppose I wanted to declare a procedure pointer to a function
> that took one double-precision argument with keyword X= and returned
> a double-precision result?
>
> procedure(DCOS), pointer :: p1

See the part of my post that you elided, where I said:

>> Yes, I know you can invent a case where one could use it. But such
>> things are so rare that I do not recall ever once seeing such a case
>> in code "in the wild", as opposed to code where people are trying to
>> illustrate how it might be used.

Your example falls perfectly into my description of "code where people
are trying to illustrate how it might be used." As does anything
containing words like "suppose".

And no, I wouldn't use it that way. If I had a handy user-written
specific, I might use it for such a "template", but I would not use
DCOS. I'd write an abstract interface body first.

Of course, it *CAN* be used like that. But that doesn't mean I advise it
or have ever seen it done in the wild. One can also use DCOS as a silly
way to generate the value 1.0d0 by writing DCOS(0.0D0), but I wouldn't
do that either.

jski

unread,
Sep 12, 2012, 11:25:50 PM9/12/12
to
On Sep 11, 2:55 pm, nos...@see.signature (Richard Maine) wrote:
I have two pieces of code, one in C and the translated version in
Fortran (see below). I'm translating some vibration code and am
observing small differences at a few point points. Most of the time
the numbers are in complete lockstep - down to the least significant
digit. But in this case I see both routines called with the exact
same arguments BUT the iC vectors (return values) differ:

Fortran iC: (-1.0380980788614978e-06, 1.0380980788614978e-06,
-4.4292627138983793e-35)
C iC: (-1.0380980788614978e-06, 1.0380980788614978e-06, 0.0)

where bC = (-1.0380980788614978d-06, 1.0380980788614978d-06, 0.0)

(gdb) geometry::inert_coord (psi=0, theta=-6.3936888239590959e-13,
phi=6.3936888239590959e-13, bc=..., ic=...) at plates.f95:910

subroutine inert_coord(psi, theta, phi, bC, iC)

double precision, intent(in) :: psi
double precision, intent(in) :: theta
double precision, intent(in) :: phi
double precision, intent(in) :: bC(3)
double precision, intent(out) :: iC(3)

iC(1) = (cos(psi)*cos(theta))*bC(1)
+ &
(-sin(psi)*cos(phi) + cos(psi)*sin(theta)*sin(phi))*bC(2)
+ &
(sin(psi)*sin(phi) + cos(psi)*sin(theta)*cos(phi))*bC(3)

iC(2) = (sin(psi)*cos(theta))*bC(1)
+ &
(cos(psi)*cos(phi) + sin(psi)*sin(theta)*sin(phi))*bC(2)
+ &
(-cos(psi)*sin(phi) + sin(psi)*sin(theta)*cos(phi))*bC(3)

iC(3) = -sin(theta)*bC(1) + cos(theta)*sin(phi)*bC(2) +
cos(theta)*cos(phi)*bC(3)

end subroutine inert_coord

inert_coord (psi=0, theta=-6.3936888239590959e-13,
phi=6.3936888239590959e-13, bC=0xbffd1f98, iC=0xbffd1e48) at
geometry.c:40

void inert_coord(double psi, double theta, double phi, double bC[3],
double iC[3])
{
iC[0] = (cos(psi)*cos(theta))*bC[0] +
(-sin(psi)*cos(phi) + cos(psi)*sin(theta)*sin(phi))*bC[1] +
(sin(psi)*sin(phi) + cos(psi)*sin(theta)*cos(phi))*bC[2];

iC[1] = (sin(psi)*cos(theta))*bC[0] +
(cos(psi)*cos(phi) + sin(psi)*sin(theta)*sin(phi))*bC[1] +
(-cos(psi)*sin(phi) + sin(psi)*sin(theta)*cos(phi))*bC[2];

iC[2] = -sin(theta)*bC[0] + cos(theta)*sin(phi)*bC[1] +
cos(theta)*cos(phi)*bC[2];
}

Why?

---John

glen herrmannsfeldt

unread,
Sep 13, 2012, 12:43:23 AM9/13/12
to
jski <john.chl...@gmail.com> wrote:

(snip on COS vs. DCOS)

> I have two pieces of code, one in C and the translated version in
> Fortran (see below). I'm translating some vibration code and am
> observing small differences at a few point points. Most of the time
> the numbers are in complete lockstep - down to the least significant
> digit. But in this case I see both routines called with the exact
> same arguments BUT the iC vectors (return values) differ:

> Fortran iC: (-1.0380980788614978e-06, 1.0380980788614978e-06,
> -4.4292627138983793e-35)
> C iC: (-1.0380980788614978e-06, 1.0380980788614978e-06, 0.0)

> where bC = (-1.0380980788614978d-06, 1.0380980788614978d-06, 0.0)

> (gdb) geometry::inert_coord (psi=0, theta=-6.3936888239590959e-13,
> phi=6.3936888239590959e-13, bc=..., ic=...) at plates.f95:910

It might not be the problem, but does look suspicious:

Note that Fortran constants are by default single precision, even
if written with many more digits. Single precision on most current
processors is about 7 decimal digits, double precision about 15.
Either a D exponent or trailing _kind indicator with the appropriate
kind value is needed.

On the other hand, C defaults to double precision unless a floating
point constant has a trailing f.

The result of getting that wrong will tend to give answers that
are the same to about 6 digits, and then different after that.

Depending on how a value is actually used, the effect can be anywhere
from nothing to every digit wrong, but first order will be about
seven digits the same.

-- glen

jski

unread,
Sep 13, 2012, 4:45:03 AM9/13/12
to
On Sep 13, 12:43 am, glen herrmannsfeldt <g...@ugcs.caltech.edu>
wrote:
Actually there are no constants involved. I was simply cutting and
pasting from 2 GDB sessions: one running my Fortran code, the other
running my C code. The values that I sent where simply the current
values for those variable - i.e., arguments to the 2 routines - at the
same place in the logic and the same iteration (i.e., time).

The interesting thing is, I gave up trying to figure out why the
values for a given variable in the code using 2 concurrent GDB
sessions (Fortran and C) were not identical. I ran the RK code and
the important values I was trying to measure for any given plate (this
is an 11 x 11 grid of plates connected by springs) - the deflection -
are almost identical (between the Fortran and C versions) for any
plate. So it's good. Curious?

---John

---John

jski

unread,
Sep 13, 2012, 5:01:29 AM9/13/12
to
The following code does result in: -4.42926271389837933E-035.
Consistent with what I was seeing in my GDB session.

module X
implicit none

contains

double precision function inert_coord_z(psi, theta, phi, bC)

double precision, intent(in) :: psi
double precision, intent(in) :: theta
double precision, intent(in) :: phi
double precision, intent(in) :: bC(3)

inert_coord_z = -sin(theta)*bC(1) + cos(theta)*sin(phi)*bC(2) +
cos(theta)*cos(phi)*bC(3)

end function inert_coord_z

end module X

program test
use X

implicit none

double precision :: bC(3) = (/-1.0380980788614978d-06,
1.0380980788614978d-06, 0.0d+0/)
double precision :: result

result = inert_coord_z(0.0d+0, -6.3936888239590959d-13,
6.3936888239590959d-13, bC)

write(*,*) result

end program test

dpb

unread,
Sep 13, 2012, 8:01:15 AM9/13/12
to
On 9/13/2012 4:01 AM, jski wrote:
...

>
> The following code does result in: -4.42926271389837933E-035.
> Consistent with what I was seeing in my GDB session.
>
> module X
> implicit none
> contains
> double precision function inert_coord_z(psi, theta, phi, bC)
...
> inert_coord_z = -sin(theta)*bC(1) + cos(theta)*sin(phi)*bC(2) +
> cos(theta)*cos(phi)*bC(3)
> end function inert_coord_z
> end module X

> program test
> use X
> implicit none
> double precision :: bC(3) = (/-1.0380980788614978d-06,
> 1.0380980788614978d-06, 0.0d+0/)
> double precision :: result
> result = inert_coord_z(0.0d+0, -6.3936888239590959d-13,
> 6.3936888239590959d-13, bC)
> write(*,*) result
> end program test

C:\Temp> df /nologo jski.f90
jski.f90

C:\Temp> jski
0.000000000000000E+000

C:\Temp> df -ver
Compaq Visual Fortran Optimizing Compiler Version 6.6 (Update C)
Copyright 2003 Compaq Computer Corp. All rights reserved.

Fignewton of the GCC RTL, apparently. Somebody else may try current
IFORT or others...

--

Ron Shepard

unread,
Sep 13, 2012, 10:04:30 AM9/13/12
to
In article
<e61044e8-9bc7-4216...@l14g2000yqo.googlegroups.com>,
jski <john.chl...@gmail.com> wrote:

> The following code does result in: -4.42926271389837933E-035.
> Consistent with what I was seeing in my GDB session.
>
> module X
> implicit none
>
> contains
>
> double precision function inert_coord_z(psi, theta, phi, bC)
>
> double precision, intent(in) :: psi
> double precision, intent(in) :: theta
> double precision, intent(in) :: phi
> double precision, intent(in) :: bC(3)
>
> inert_coord_z = -sin(theta)*bC(1) + cos(theta)*sin(phi)*bC(2) +
> cos(theta)*cos(phi)*bC(3)
>
> end function inert_coord_z
>
> end module X

Just to see what happens, try putting parentheses in that expression
in order to force various orders of evaluation for those three
terms. There are three ways to evaluate the sum of three terms
assuming the addition operation is commutative (and I think 12 ways
without that assumption), and you will probably get different
answers for all these possibilities. Then if you also factor out
any common subexpressions (such as the cos(theta) factor in the last
two terms) and evaluate the expression in various ways, you may get
even more slightly different results because floating point
multiplication is not associative.

The fortran compiler is free to evaluate the expression in any
mathematically equivalent way it wants, assuming both commutative
addition and multiplication and also associative multiplication.
Those properties do not apply to floating point arithmetic because
of rounding or truncation of intermediate results, the use of
extended precision registers, and other hardware features. However,
the fortran compiler must respect parentheses placed there by the
programmer in order to force a specific operation order. At one
time, the C language did not require parentheses to be respected, so
depending on which C language version you are using, you may not
have the same control over the evaluation order there.

$.02 -Ron Shepard

john.chl...@gmail.com

unread,
Sep 13, 2012, 11:55:45 AM9/13/12
to
Of course, I'm using GNU Fortran (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2) on Fedora 16.

John Harper

unread,
Sep 13, 2012, 6:22:01 PM9/13/12
to
On an x86-64 machine:
gcc 4.0.3 (g95 0.92!) Jun 24 2009 wrote 0.
gfortran 4.4.6 20110731 wrote 0.0000000000000000E+000
ifort version 12.1.3 wrote 0.00000000000000
Sun Fortran 8.6 wrote 0.0E+0

On an i386 machine:
gcc 4.0.3 (g95 0.92!) Jan 19 2011 wrote -4.4292627138983793E-35
gfortran 4.8.0 20120701 wrote -4.4292627138983793E-35

But what's the big deal? Inert_coord_z is adding numbers of order 6d-19 and
-6d-19, and epsilon(1d0) is about 2d-16 in all the systems I tried, so of
course different systems might differ by around 12d-35. That they only
differ by 4d-35 is cause for happiness not complaints!

--John Harper

robert....@oracle.com

unread,
Sep 17, 2012, 4:27:22 AM9/17/12
to
My guess is that x87 instructions are involved. I suspect that gfortran is using the x87 instructions and gcc is not. Another possibility is that both compilers are using the x87 instructions, but that gcc is chopping back the precision of the function results and gcc does not.

Robert Corbett

Tobias Burnus

unread,
Sep 17, 2012, 4:55:18 AM9/17/12
to
On 09/17/2012 10:27 AM, robert....@oracle.com wrote:
>> I have two pieces of code, one in C and the translated version in
>> >
>> >Fortran (see below). I'm translating some vibration code and am
>> >
>> >observing small differences at a few point points. Most of the time
>> >
>> >the numbers are in complete lockstep - down to the least significant
>> >
>> >digit. But in this case I see both routines called with the exact
>> >
>> >same arguments BUT the iC vectors (return values) differ:
>> >
>> >

> My guess is that x87 instructions are involved. I suspect that gfortran
> is using the x87 instructions and gcc is not. Another possibility is
> that both compilers are using the x87 instructions, but that gcc is
> chopping back the precision of the function results and gcc does not.


In principle, GCC treats Fortran and C in the same way.* However, since
GCC 4.5, GCC's C compiler supports -fexcess-precision=standard which is
enabled with e.g. -std=c99. See:

http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fexcess_002dprecision-886

Try -mfpmath=sse or -ffloat-store. (The former option requires that
-march= explicitly or implicitly specifies a CPU which supports SSE.)
SSE doesn't have the excess precision and float-store moves the variable
out of the register and back to get rid of the excess precision. (On a
64bit x86-64 CPU, SSE is used by default.)

Of course, one can also explcitly use the excess precision via
gfortran's REAL(10) which matches GCC's long double (on x86/x86-64
hardware). Or [with GCC 4.6 and later] you could use REAL(16)/__float128
(on C together with libquadmath's sinq etc.) to have even more precision
and lower performance ;-)

Tobias

* There are some exceptions like how parentheses are handled for
optimizations or for the handling of complex variables.
0 new messages