From: Simon Geard on
What is the best way to define mathematical constants for use in
Fortran? For example I could define

module Constants
real(8), parameter :: E = 2.718281828459045d0 ! e
real(8), parameter :: PI = 3.141592653589793d0 ! pi
end module Constants

but there are other possibilities. Is there a recommended standard/best
practice? Is there a 'constants' module in the 2008 spec?

Thanks,

Simon


From: Arjen Markus on
On 18 jan, 14:46, Simon Geard <si...(a)whiteowl.co.uk> wrote:
> What is the best way to define mathematical constants for use in
> Fortran? For example I could define
>
> module Constants
>   real(8), parameter :: E = 2.718281828459045d0  ! e
>   real(8), parameter :: PI = 3.141592653589793d0 ! pi
> end module Constants
>
> but there are other possibilities. Is there a recommended standard/best
> practice? Is there a 'constants' module in the 2008 spec?
>
> Thanks,
>
> Simon

I'd say that the above is the most reliable way to define them.
You could use transcendental functions like exp() and atan() to get
mathematically sane expressions for at least these two constants,
but you will run into trouble with cross-compiling (the compiler
would have to emulate the transcendental functions of the target
platform) and the standard does not necessarily allow all such
functions in such an initialisation expression (if I understand
it correctly, precisely for that reason).

More importantly perhaps, the results of your program might
depend on the quality of the library routines that you would
be using.

Using literal constants (especially in double precision and
enough digits) is the most robust way to achieve what you
want.

Regards,

Arjen

PS I will be happy to add such a module to my flibs project :).
From: James Van Buskirk on
"Arjen Markus" <arjen.markus895(a)gmail.com> wrote in message
news:c1758405-8d2f-4709-95ab-b9e4967e3236(a)21g2000yqj.googlegroups.com...

On 18 jan, 14:46, Simon Geard <si...(a)whiteowl.co.uk> wrote:

> > What is the best way to define mathematical constants for use in
> > Fortran? For example I could define

> > module Constants
> > real(8), parameter :: E = 2.718281828459045d0 ! e
> > real(8), parameter :: PI = 3.141592653589793d0 ! pi
> > end module Constants

> > but there are other possibilities. Is there a recommended standard/best
> > practice? Is there a 'constants' module in the 2008 spec?

> I'd say that the above is the most reliable way to define them.
> You could use transcendental functions like exp() and atan() to get
> mathematically sane expressions for at least these two constants,
> but you will run into trouble with cross-compiling (the compiler
> would have to emulate the transcendental functions of the target
> platform) and the standard does not necessarily allow all such
> functions in such an initialisation expression (if I understand
> it correctly, precisely for that reason).

Actually, f03 makes initialization expressions much more of a free-
fire zone. In f95 there was a separate class of constant expressions
which lacked self-consistency and required the vendor to provide 4
effective compilers (one for ordinary expressions, one for
specification expressions, one for initialization expressions, and
one for constant expressions) but the first corregendum to f95
eliminated consant expressions by editing out their effects
throughout the standard. Later, an f95 constant expression was made
to be an f03 initialization expression, and transcendental functions
and transformational functions became fair game at this point.
There were some rough edges involved in these changes and in fact
as a result you can write code that should behave differently under
the f95 and f03 standards, but the differences are esoteric enough
that I don't think any compiler actually catches them when the f95
standard is enforced.

gfortran is the most agile cross compiler out there and it does use
a gpl software package to compute initialization expressions. For
it at least the initialization expression results are often more
accurate than the ordinary expression results:

C:\gfortran\clf\accurate_init>type accurate_init.f90
module funcs
implicit none
integer, parameter :: dp = selected_real_kind(15,300)
contains
subroutine sub(x)
real(dp) x
real(dp) y

y = cos(cmplx(atan(real(1,kind(x))),x,kind(x)))
write(*,*) y
end subroutine sub
end module funcs

program accurate_init
use funcs
implicit none
real(dp), parameter :: x = &
cos(cmplx(atan(real(1,kind(x))),log(huge(x))+1,kind(x)))
real(dp) y

write(*,*) x
y = log(huge(x))+1
call sub(y)
end program accurate_init

C:\gfortran\clf\accurate_init>gfortran accurate_init.f90 -oaccurate_init

C:\gfortran\clf\accurate_init>accurate_init
1.72768693203654562E+308
+Infinity

This is one where it's tricky to avoid overflow and the initialization
expression package is powerful enough (and maybe slow enough) to get
the right result.

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


From: robert.corbett on
On Jan 18, 6:17 am, Arjen Markus <arjen.markus...(a)gmail.com> wrote:

> More importantly perhaps, the results of your program might
> depend on the quality of the library routines that you would
> be using.

I would like to second this. Although there are many
compilers that have trouble converting floating-point
constants to internal values with complete accuracy,
your odds are much better with literal constants than
with transcendental functions.

Bob Corbett
From: Paul Hirose on
"Simon Geard" <simon(a)whiteowl.co.uk> wrote in message
news:hj1oo1$5k2$1(a)news.eternal-september.org...
> What is the best way to define mathematical constants for use in
> Fortran? For example I could define
>
> module Constants
> real(8), parameter :: E = 2.718281828459045d0 ! e
> real(8), parameter :: PI = 3.141592653589793d0 ! pi
> end module Constants

I calculate constants like those at run time. That way, someone
maintaining the code doesn't have to wonder where I got the values,
whether they contain a typo, etc.

Nowadays even a budget Windows machine does floating point in hardware
per the IEEE standard, so I believe arc cosine of -1 is a safe way to
compute pi, for example. However, I'd be interested to hear of any
cases where this would have caused trouble.

Sometimes the representation of a type is not specified by the
language. It's up to the implementer. With these languages, computing
math constants at runtime automatically upgrades their accuracy if,
say, "double precision" someday changes to a 128 bit representation.
Simply recompile your old code under the new architecture.

--
Paul Hirose <jvcmz89uwf(a)earINVALIDthlink.net>
To reply by email remove INVALID