3

How could I get constants (or parameters, I suppose) that are negative and positive infinity in Fortran 2008? I tried the following code:

program inf
  use, intrinsic :: ieee_arithmetic

  real(8), parameter :: inf_pos = ieee_value(0d0, ieee_positive_inf)
  real(8), parameter :: inf_neg = ieee_value(0d0, ieee_negative_inf)
end program inf

However, I get the following errors:

$ gfortran inf.f08
inf.f08:4:22:

   real(8) :: inf_pos = ieee_value(0d0, ieee_positive_inf)
                  1
Error: Function ‘ieee_value’ in initialization expression at (1) must be an intrinsic function
inf.f08:5:22:

   real(8) :: inf_neg = ieee_value(0d0, ieee_negative_inf)
                  1
Error: Function ‘ieee_value’ in initialization expression at (1) must be an intrinsic function

Despite documentation saying otherwise, it seems that gfortran thinks that ieee_value() isn't intrinsic.

Is there anyway to get what I'm trying to do?

francescalus
  • 30,576
  • 16
  • 61
  • 96
junius
  • 570
  • 3
  • 14
  • Which documentation says that `ieee_value` is an intrinsic function? It isn't, and if you point to that we can address that part for you. – francescalus May 30 '18 at 18:16
  • [This question](https://stackoverflow.com/q/31971836/3157076) talks about NaNs. Whilst I won't relate the questions as duplicates there is enough for you to read in the short term. – francescalus May 30 '18 at 18:17
  • http://pleiades.ucsc.edu/doc/intel/composer_xe/14.0/compiler_f/main_for/GUID-0B22F67E-7685-404E-AF7E-F7A83C8C2E4D.htm This page seems to imply it. But regardless, that's neither here nor there – junius May 30 '18 at 18:17
  • @francescalus wouldn't using `transfer()` be non-portable across big and little endian architecture? – junius May 30 '18 at 18:20
  • Oh yes. Alas, if you want named constants you don't have many other options. And not just endianness but all other aspects of representation). – francescalus May 30 '18 at 18:21
  • I don't think endianness is an issue. Endianness is about the order of storing individual bytes in memory, but a 32-bit number still has bytes 0-31 and those are the same whatever the endianness is. You care about endianness when acessing individual bytes in memory using pointers or equivalence or when storing them to external files. – Vladimir F Героям слава May 30 '18 at 18:43
  • ALthough I see I warned about endianness in my linked answer... I am not sure, but I think it is fine. – Vladimir F Героям слава May 30 '18 at 18:46

3 Answers3

3

I'll first look at why you can't use ieee_value to give the value for your desired named constant, then I'll give bad news. Both are interesting (to me).

ieee_value isn't an intrinsic procedure. It's a procedure in an intrinsic module but as the Fortran 2008 standard notes (Note 13.25):

The types and procedures defined in standard intrinsic modules are not themselves intrinsic.

gfortran is correct to note that ieee_value may not be used in an initialization (constant) expression.

Now, if you need to initialize a named constant with an "infinite" value there are non-portable options:1.

  • similar to this question about NaNs you can work out the required bit pattern and initialize with transfer;
  • you may be able to write an "overflowing" initialization expression.

You can work around the non-portable nature of this with your build system and pre-processor.

That all said, you may not need to have an infinite named constant. The IEEE modules easily provide procedures for "is this value infinite?", or "set this value to be infinite". Your compiler may also have "initialize variable to infinity" as a compile-time option.


1 Outside initialization expressions the restrictions on using ieee_value are much looser.

francescalus
  • 30,576
  • 16
  • 61
  • 96
1

The somewhat inelegant solution I came up with was to simplify define functions which always return positive and negative infinity

program inf
  use, intrinsic :: ieee_arithmetic

  print *, inf_pos()
  print *, inf_neg()

contains
  pure function inf_pos() result(r)
    real(8) :: r
    r = ieee_value(0d0, ieee_positive_inf)
  end function inf_pos

  pure function inf_neg() result(r)
    real(8) :: r
    r = ieee_value(0d0, ieee_negative_inf)
  end function inf_neg
end program inf
junius
  • 570
  • 3
  • 14
0

The following would yield + and - Infinity, however, must be executed and is not accepted as initialisation directly in the variable declaration:

program testinf
implicit none
double precision :: x, xiplus, xineg   
x       = HUGE(x)
xiplus  = 2 * x     ! yields +Infinity
xineg   =-2 * x     ! yields -Infinity
write(*,*)x , xiplus, xineg 
end program testinf
Michael
  • 42
  • 3