Confusing type checking report by NAG Fortran

117 Views Asked by At

Consider the following Fortran code:

program kinds_demo
  use iso_fortran_env, only: REAL64, INT32
  integer(int32), parameter :: n=10
  real(real64)    :: A(n, n)
  complex(real64) :: B(n, n)
  real(real64)    :: tr, u(n*n), v(n*n)

  a=1.0D0
  b=1.0D0
  
  call dcopy(n*n, a, 1, u, 1)
  call dcopy(n*n, b, 2, v, 1)
  
  tr=dot_product(u,v)

  print*,tr
  
end program kinds_demo

I compile it with newest NAG Fortran compiler (NAG Fortran Compiler Release 7.1(Hanzomon) Build 7114)

nagfor -c -o kinds_demo.x kinds_demo.f90

and get this error message

Error: kinds_demo.f90, line 12: Inconsistent data type COMPLEX(KIND(0d0)) (previously DOUBLE PRECISION) for argument 2 in reference to DCOPY

This is an expected error that only becomes evident by comparing the two dcopy calls. Upon commenting line 11 (first call) the program becomes valid as expected. Notice, I am not linking here. Therefore, the actual type of arguments is irrelevant here, only their consistency matters. But I do not understand the error message. Shouldn't it be written as

Error: kinds_demo.f90, line 12: Inconsistent data type COMPLEX(2) (previously REAL(2)) for argument 2 in reference to DCOPY

Notice that REAL64=2 for the NAG compiler.

It is emphasized many times here that double precision is not REAL64, but somehow NAG compiler (which is known for additional error checking and tools capabilities) assumes just opposite?

1

There are 1 best solutions below

9
On

Kind parameters are numbers. Consider:

use, intrinsic :: iso_fortran_env, only : real32  ! Value 1
use, intrinsic :: iso_c_binding, only : c_float   ! Value 1

implicit none

real(kind=1) a
real(kind=5**0) b
real(kind=SELECTED_REAL_KIND(radix=6)) c          ! Kind value 1
real(kind=real32) d
real(kind=c_float) e
real f                                            ! Default real has kind 1

end

where all those expressions for the kind evaluate to 1. Each of those variables are the same type and kind (default real, kind 1).

When a compiler sees a constant expression where a kind parameter is required, it evaluates the expression and uses the value. While a compiler can store the actual constant name/expression used in declaring an object to enhance later error message reporting, this is not common.

Many compilers will complain, not as NAG has chosen with an explanation, simply with the numeric value:

Error: Type mismatch between actual argument at (1) and actual argument at (2) (COMPLEX(8)/REAL(8)).

The NAG compiler is choosing to take a value and express it in a more descriptive way with the mapping (using the default 1,2,3 numbering scheme):

  • kind value 1 -> "real" / "complex"
  • kind value 2 -> "double precision" / "complex(kind(0d0)"
  • kind value 3 -> "real(real128)" / "complex(real128)

(for the "odd" kind 2, note that "double complex" is a non-standard extension offered by compilers other than NAG's and "complex(double precision)" wouldn't work)

Now, we've stressed previously that "double precision" is not "real(128)". By this, we don't mean kind(0d0)/=real128, but that the two values aren't necessarily the same. They may be the same.

The mapping is intended to be more helpful than a naked number, rather than perfectly expressing the code that was seen (at a different compilation stage). Usually, that's all that's required. Recall that NAG supports different numbering schemes for kinds (-kind=sequential, -kind=byte and -kind=unique): using the numeric values can cause other confusion.

As usual, if you think a compiler's error message could be improved, please do contact the compiler vendor with your suggestion. If the developers agree and see it as worthwhile, perhaps with dozens of other requests, the error message and diagnostics may be changed to what you'd prefer.