On 7/27/20 11:37 AM, spectrum wrote:
> My local note says that IEEE_VALUE() becomes an intrinsic function from
> F2018 (?), so the above result is probably because the feature is too new.
>
> If so, is there any alternative way to initialize variables with NaN
> at compile time, hopefully in a portable manner?
> (I am sorry that this is probably a recurrent question,
> but I would like to know "best practice" as of 2020-7).
You might try something like this:
program ieeeNaN
use ieee_arithmetic
implicit none
integer, parameter :: wp = ieee_selected_real_kind(14)
real(wp) :: x
real(wp), parameter :: xNaN = real(Z'FFF8000000000000',kind=wp)
write(*,*) 'support=', ieee_support_nan(x)
x = ieee_value( 1.0_wp, ieee_quiet_nan ) !! assignment at run time
write(*,*) x !! => NaN (gfort-8/10)
write(*,'(z16)') x
write(*,*) xNaN, ieee_is_nan(xNaN)
end
As for "best practices," I think you will just get a lot of opinions
about what is the best compromise.
First, if you are concerned with portability, then maybe you should not
use IEEE specific operations because that limits you right off the bat
to ieee hardware and to compilers that support the ieee_arithmetic module.
If that pair of limitations is acceptable (they are to me), then notice
how I removed your hard-coded "8" types. I also removed your "1.0d0"
literal constant. I replaced them with the integer kind parameter "wp".
You should never hard coded types, either in declarations or in
literals, that's just ugly. And mixing double precision constants with
the "d" exponent with ieee types is just confusing and weird. It is all
like turning a silk purse into a sow's ear.
Just do the straightforward thing and define a parameter of the correct
type and use it. You don't need to depend on all of those other
assumptions (that wp==8 and that double precision is the same as wp).
Ok, so next, you can see that I printed out the Nan value with a Z
format. That's not standard. Most compilers support it, but it's not
really portable. It works for gfortran, which I know you are using, so I
did it for this posting. There are other ways to print out those hex
values, all ugly, so do one of those if you must.
Once you see the hex representation of Nan, then you can define a real
parameter to have that bit pattern. There was a recent thread about the
funky syntax needed to do that, but I think the above is now standard.
It was not standard in f90, but it is now, so there may be portability
issues related to just using the REAL() intrinsic.
Even if the ieee_arithmetic module is supported, and the bit pattern is
defined by the ieee standard itself, that does not mean that hex
constant is necessarily portable. There may be other issues related to
bit ordering or to byte ordering within the REAL data value. That
constant above should be fairly portable, but it is not required to be
so by either the fortran standard or the ieee standard.
Note that I added a ieee_support_nan(x) reference. Even if ieee
arithmetic is supported, that does not mean that NaN is supported. If
your code requires that, then you should check to make sure and stop if
necessary. I also added a ieee_is_nan() reference just to double check
that the hex value is interpreted as a NaN. For portability reasons, you
probably should do that test too, and stop if things don't match up.
If you want to initialize values at compile time with the xNaN
parameter, and if you are concerned with portability, then you should
define the parameter xNaN in a module by itself and isolate all of those
potential nonportable trip wires in one place. Every place in your code
that you want to use a Nan constant, it should USE that module and refer
to the xNAN parameter. That way, if something goes haywire, all of your
code will get fixed once that one module works correctly.
When f2018 is supported, then this all gets easier. But for now, those
are my "best practices" suggestions. They are not perfect, they are
compromises, and others may have their own opinions.
$.02 -Ron Shepard