Zero(dble) type of function

It is a good practice to use something like:

integer, parameter :: dp = kind(0.0d0)
real(dp) :: x

But then if want to set x to zero (or one), I would like to do:

x = zero(dp)
x = one(dp)

To be consistent with the type of the variable. Does this exist?

1 Like

Is it safe to do the other-way around? For example declaring a variable a real*4 and initialize it as x = 0.d0? There will be a type conversion or, perhaps, the compiler just fixes that?

(not that I want to do that for any reason, just trying to understand the consequences).

You can write

x = 0.0_dp
x = 1.0_dp

or

x = real(0,kind=dp)
x = real(1,kind=dp)

as discussed in the Floating Point Numbers section of Fortran Best Practices.

2 Likes

I feel safer with those :slight_smile: .

With Fortran, you are more likely (even if not all that prevalent) to come across codes with the following than functions such as zero/zeros and one/ones that are more common with other languages such as Julia:

real(dp), parameter :: ZERO = 0.0_dp
real(dp), parameter :: ONE = 1.0_dp
..
x = ZERO ! here x can be of any rank 
x = ONE  ! -ditto-
1 Like

real*4::x
is not Fortran, never mind safe.

2 Likes

What about dsqrt and sqrt, what is the practice to make those follow the declared type?

sqrt is a generic intrinsic such that the kind of the result is the same as that of the actual argument. The standard “way” will be to use it instead of dsqrt.

2 Likes

Are all those d-versions of the intrinsic functions obsolete?

(I’m updating myself…)

Edit: I guess it is useful if one wants to convert the return type.

Yep, this is from the standard, Section B.3.12 on `obsolescent features:

Note in Fortran, the kind is separate from type per se e.g., objects that represent floating-point quantities are of real intrinsic type, as you know. But they can be of different kinds.

Quite a few of the generic intrinsics usually tend to have an optional parameter (dummy argument in Fortran parlance) to indicate the kind of the result. Though not SQRT, LOG, etc. where it’s better left to the programmer to do so using conversion intrinsics such as REAL. See a related discussion at Intel Fortran forum.

1 Like

Maybe the responses so far have given you what you need, but to answer the original question posed, it is not possible to write a function that behaves like

integer, parameter :: dp = kind(0d0)
real(dp) :: x
x = zero(dp)

The reason is that a dummy argument cannot the kind parameter of a function result or other dummy argument. That is, the following is not valid Fortran:

function zero(k) 
  integer, intent(in) :: k
  real(kind=k) :: zero
  zero = real(0, kind=k)
end function

However, one can come close with the alternative

integer, parameter :: dp = kind(0d0)
real(dp) :: x
x = zero(x)

where zero would be a generic name for several functions, e.g.,

real(dp) function zero_dp(x) result(z)
  real(dp), intent(in) :: x
  z = 0._dp
end function

The strategy here is to resolve the desired return type using an argument with the desired kind, rather than passing the kind parameter itself.

3 Likes

Below is my naive module for some basic constants.
I can do things like,

x = one
y = zero

eh, since you alreayd defined dp,
you could just do _dp, like

x = 0_dp or x = 0.0_dp

module constants
    implicit none
    integer, public, parameter :: i4=selected_int_kind(9)
    integer, public, parameter :: i8=selected_int_kind(15)
    integer, public, parameter :: r8=selected_real_kind(15,9)
    real(kind=r8), public, parameter :: zero=0.0_r8,one=1.0_r8,two=2.0_r8,three=3.0_r8,four=4.0_r8 &
        ,five=5.0_r8,six=6.0_r8,seven=7.0_r8,eight=8.0_r8,nine=9.0_r8 &
        ,ten=10.0_r8,tenth=.1_r8,half=.5_r8,third=1.0_r8/3.0_r8,sixth=1.0_r8/6.0_r8 &
        ,pi=4.0_r8*atan(1.0_r8) &
        ,normpdf_factor=1.0_r8/sqrt(8.0_r8*atan(1.0_r8)) ! 1/sqrt(2 pi)
    complex(kind=r8), public, parameter :: czero=(0.0_r8,0.0_r8),ci=(0.0_r8,1.0_r8),cone=(1.0_r8,0.0_r8)  
end module constants
1 Like