Is it possible to set a parameter variable with NaN? and have that in a particular module. I want to use it for initialization of some other variables. Therefore, I'll be faced with a run-time error, if they are not updated, rather than simulations running with some random numbers.
I am using GFortran.

- 57,977
- 4
- 76
- 119

- 3,275
- 4
- 28
- 42
-
5For gfortran, I'd be tempted to just consider `-finit-real=nan`. – francescalus Aug 12 '15 at 17:48
-
2or `-init=arrays -init=snan` in ifort – knia Oct 11 '18 at 11:45
4 Answers
To add to Vladimir F's answer I'll mention that gfortran 5.0 (but not earlier) supports the IEEE intrinsic modules.
Instead of
real x
x=0
x=0/x
one can use
use, intrinsic :: iso_fortran_env
use, intrinsic :: ieee_arithmetic
integer(int32) i
real(real32) x
x = ieee_value(x, ieee_quiet_nan)
i = transfer(x,i)
This gives you a little flexibility over which of the NaN values you get. You also needn't worry about any signalling invalid flag. [But note that asking for ieee_signaling_nan
may not really give you that.]
Note that ieee_value()
can't be used directly in initialization: a reference to it isn't a constant expression. For such use, take this approach to get the bit pattern and apply the method of the other answer.
You'll also need to ensure that there is the support for the features for each datatype.

- 30,576
- 16
- 61
- 96
-
2True, I still did not go too much into this, as I must keep compatibility with gfortran 4.8. Unfortunately, `ieee_value` is indeed not allowed in constant expressions, so one still needs to use transfer(). Much more discussion is in https://groups.google.com/forum/#!msg/comp.lang.fortran/tYC3UgAyNrY/6TzOLbkP6tsJ – Vladimir F Героям слава Aug 12 '15 at 21:15
-
1It seems if I want to use NaN for debugging and getting run-time error, I have to use signaling NaN rather than the quiet one ( [Ref](http://stackoverflow.com/questions/18118408/what-is-difference-between-quiet-nan-and-signaling-nan) ). – Sorush Aug 13 '15 at 10:30
-
1@Sorush Yes. There is no guarantee that `ieee_signaling_nan` will result in such a thing (although it is recommended). I've no idea what gfortran returns - if you can test, please let me know. A quiet NaN is still valuable, in some sense: you know something's gone wrong. Not convenient for debugging. – francescalus Aug 13 '15 at 10:48
It is possible. You first have to find out which bit pattern represents one of the possible NaN values. You can store the bit pattern in an integer:
use, intrinsic :: iso_fortran_env
real(real64) x
integer(int64) i
x = 0
x = 0/x
print *, x
print *, transfer(x, i)
end
It gives: -2251799813685248
Then you can initialize your variables using
real(real64), parameter :: nan64 = transfer(-2251799813685248_int64, 1._real64)
Similarly for 32 bit variables you get the integer -4194304, so that you can do
real(real32), parameter :: nan32 = transfer(-4194304_int32, 1._real32)
If you are using IEEE-754 compatible floating point representation (almost certain, when you care about NaNs), you can also use the definitions from that standard. There are many possible bit patterns that mean a not-a-number. They have all bits in the exponent equal to 1 and some bit in the mantissa equal to 1. One can use convertors such as https://www.h-schmidt.net/FloatConverter/IEEE754.html
If you need to distinguish signaling and quiet NaNs, the quiet NaNs have the first bit (most significant) in the mantissa equal to one and the signaling NaNs have the first bit equal to zero. But as https://faculty.cc.gatech.edu/~hyesoon/spr09/ieee754.pdf notes: "SNaNs, which exist mainly for political reasons and are rarely used". The convertor referenced above does not show this difference.
For example:
use, intrinsic :: iso_fortran_env
use ieee_arithmetic
real(real32), parameter :: qnan = transfer(int(B'01111111110000000000000000000000',int32), 1._real32)
real(real32), parameter :: snan = transfer(int(B'01111111101000000000000000000000',int32), 1._real32)
if (IEEE_SUPPORT_DATATYPE(qnan)) then
print *, "qnan:", (ieee_class(qnan)==ieee_quiet_nan)
end if
if (IEEE_SUPPORT_DATATYPE(snan)) then
print *, "snan:", (ieee_class(snan)==ieee_signaling_nan)
end if
end
returns
qnan: T
snan: T
in Intel Fortran in default settings. In GCC (gfortran) signaling NaNs are disabled by default. and can be enabled by -fsignaling-nans
, but it does not seem to help anyway.
Other bits, including the first sign bit, are usually ignored.
Many compilers have an option to do that for you for all real variables. As francescalus shows, in gfortran it is -finit-real=nan
. Doing that manually gives you a finer control.
Disclaimer: Be careful when switching to a different platform. Endianness and other issues could play a role, even though I think it could be actually OK. I assumed an IEEE conforming CPU.
See, francescalus's answer for an alternative which uses a standard function. Unfortunately, it is not applicable for parameter
constants, but is useful.

- 57,977
- 4
- 76
- 119
-
I agree with your suggestion @Vladimir F as in this way during the run-time it is possible to change value of a variable to NaN or vice versa. But the drawback is the machine-dependent bit pattern of NaN. – Sorush Aug 12 '15 at 18:26
If you are stuck with a GFortran that does not have the intrinsic IEEE but does have the intrinsic iso_c_binding (like the one needed to build R on Windows), the following works and is equivalent to the C and R NaN (passes is.nan
on R):
real(kind = c_double), parameter :: ONE = 1_c_double
real(kind = c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', ONE)
Interestingly, real(kind = c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', 1_c_double)
fails my check for is.nan
.

- 1,655
- 19
- 32
-
2Are you aware that `1_c_double` is an integer? After realizing that you will not find the fail that much interesting any more. Your first line can be just `real(kind = c_double), parameter :: ONE = 1` and it will do the same. See my answer for proper syntax for reals. – Vladimir F Героям слава Feb 03 '17 at 09:32
-
2So in the end you can just shorten it to `real(c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', 1._c_double)` or `real(c_double), parameter :: NAN = TRANSFER(9218868437227405313_c_int64_t, 1._c_double)` – Vladimir F Героям слава Feb 03 '17 at 09:42
-
-
Aren't BOZ literals only allowed in data statements and some specific intrinsic for manipulating bits? – Rodrigo Rodrigues May 30 '18 at 19:15
-
@RodrigoRodrigues See (https://gcc.gnu.org/onlinedocs/gfortran/BOZ-literal-constants.html). "*Up to Fortran 95, BOZ literals were only allowed to initialize integer variables in DATA statements. Since Fortran 2003 BOZ literals are also allowed as argument of REAL, DBLE, INT and CMPLX; the result is the same as if the integer BOZ literal had been converted by TRANSFER to, respectively, real, double precision, integer or complex. As GNU Fortran extension the intrinsic procedures FLOAT, DFLOAT, COMPLEX and DCMPLX are treated alike.*" – Avraham May 31 '18 at 15:46
-
Constraint C7110 (R764) from 2015 standard: "A boz-literal-constant shall appear only as a data-stmt-constant in a DATA statement, or where explicitly allowed in subclause 16.9 as an actual argument of an intrinsic procedure." But TRANSFER intrinsic does not mention them, unlike the type conversion and bit manipulation intrinsics. – Rodrigo Rodrigues May 31 '18 at 17:03
As pointed out by francescalus and in this discussion, the result of ieee_value
cannot be assigned to a parameter
. Another approach is using a protected
module variable instead of a parameter
. However, then one has to call a model initialization function at the start of the program.
module nan_module
implicit none
real, protected :: nan_real
contains
subroutine init_nan_module
use, intrinsic :: ieee_arithmetic
implicit none
nan_real = ieee_value(nan_real, ieee_quiet_nan)
end subroutine
end module nan_module
program test
use nan_module, only: init_nan_module, nan_real
implicit none
real :: x
call init_nan_module()
x = nan_real
write(*,*) x, 'isnan', isnan(x)
end program test

- 41
- 3