Complex addition returns NaN

Hi all,
I wrote a fortran module called arithmetic_mod in order to handle different type of input values such as integer, real and complex as follows:

module arithmetic_mod
    implicit none
    private
    public :: adder
    interface adder
        procedure int_add, real_add, complex_add
    end interface adder
contains
    ! Adder Functions
    integer function int_add(n_1, n_2)
        integer, intent(in) :: n_1, n_2
        integer :: sum
        sum = n_1 + n_2
    end function int_add

    real function real_add(n_1, n_2)
        real, intent(in) :: n_1, n_2
        real :: sum
        sum = n_1 + n_2
    end function real_add

    complex function complex_add(n_1, n_2)
        complex, intent(in) :: n_1, n_2
        complex :: sum
        sum = n_1 + n_2
    end function complex_add
end module arithmetic_mod

I tried to test the module in a separate file as follows:

program test
    use arithmetic_mod
    implicit none
    integer :: i_num_1 = 2, i_num_2 = 3
    real :: r_num_1 = 25.0, r_num_2 = 35.0
    complex :: com_num_1 = (7, 8), com_num_2 = (5, -7)

    print "(a8,i1)", "2 + 3 = ", adder(i_num_1, i_num_2)
    print "(a14,f4.1)", "25.0 + 35.0 = ", adder(r_num_1, r_num_2)
    print*, adder(com_num_1, com_num_2)
end program test

and i compiled these files using commands below:

gfortran -c arithmetic_mod.f90 test_arithmetic.f90
gfortan arithmetic_mod.o test_arithmetic.f90

But when i ran ./a.out , i got output below:
2 + 3 = 5
25.0 + 35.0 = 60.0
(NaN, NaN)

The questions is why complex adder returns NaN instead of correct output(12.000000, 1.000000)?

The problems are in your 3 functions. The results are not set up properly. You have two options to solve the problem, for the integer adder:

  1. you must define the result with the function name “int_add”:

int_add = n_1 + n_2

instead of

sum = n_1 + n_2

  1. or you can add result(sum), after function int_add(n_1, n_2). So that you have:

function int_add(n_1, n_2) result(sum)

instead of

integer function int_add(n_1, n_2)

1 Like

@ELNS,

You may have noted Fortran as a programming language has a standard and is supported by more than processor with different levels of support and guidance for practitioners. If you were to try Intel Fortran compiler in a “pedantic” mode on the code you show in the original post, you could get a response as follows:

C:\temp>ifort /c /warn:errors arithmetic_mod.f90
Intel® Visual Fortran Intel® 64 Compiler for applications running on Intel® 64, Version 19.1.1.216 Build 20200306
Copyright © 1985-2020 Intel Corporation. All rights reserved.

arithmetic_mod.f90(10): error #6178: The return value of this FUNCTION has not been defined. [INT_ADD]
integer function int_add(n_1, n_2)
---------------------^
arithmetic_mod.f90(16): error #6178: The return value of this FUNCTION has not been defined. [REAL_ADD]
real function real_add(n_1, n_2)
------------------^
arithmetic_mod.f90(22): error #6178: The return value of this FUNCTION has not been defined. [COMPLEX_ADD]
complex function complex_add(n_1, n_2)
---------------------^
compilation aborted for arithmetic_mod.f90 (code 1)

C:\temp>

Unfortunately with gfortran even with its “pedantic” settings, the compiler raises no alerts to bring your attention to the issue. Perhaps you can get involved with the GCC gfortran community and contribute toward compiler enhancements that can help you and other future Fortranners like you who may be using gfortran whilst learning the language:

C:\temp>gfortran -c -std=f2018 -Wpedantic -pedantic-errors arithmetic_mod.f90

C:\temp>

1 Like

@kargl wrote:

The option -pedantic should be avoided (unless you actually know about some of its idiocracies).

I refer to this site (https://gcc.gnu.org/onlinedocs/gfortran/Error-and-Warning-Options.html#Error-and-Warning-Options) when I point gfortran compiler options to readers. The description of ‘-pedantic’ option therein doesn’t give me the same sense of avoidance as above comment.

Anyways I only thought of ‘pedantic’ because the Fortran standard places the responsibility squarely on the programmer to define the function result in a subprogram and it doesn’t require the compiler to diagnose the absence of such definition though compilers can go the extra yard in helping their users if they choose to do so. So a mode where a warning along such lines, possibly upgraded to an error, catches the attention of a programmer comes as a good pedantic aid. Hence my choice of -Wpedantic along with -pedantic-errors.

But when gfortran didn’t issue an alert with ‘pedantic’ and given the statement in the above link which says, “improvements to GNU Fortran in this area are welcome,” it appeared to me the GCC gfortran community is open to compiler enhancements on this aspect where OP can make useful contributions also.

3 things pop out right away:

  1. You need to define the function result variable before completing execution of a function.
  2. Using the name of an intrinsic function (such as SUM) as a variable name is generally confusing and not a good programming form.
  3. Fortran already has overloaded the + operator to do what this module is attempting. It does not make sense to write a module like this, unless it is an exercise in learning how generic interfaces work.
1 Like

My habits in the debugging phase are to use those options:

$ gfortran -Wall -Wextra -std=f2008 -pedantic -g my_program.f90
  • -Wextra will give more warnings
  • -g adds debugging information into the executable

The option -fbounds-check can also be interesting to check array bounds at execution.
See for example:
https://faculty.washington.edu/rjl/uwamath583s11/sphinx/notes/html/gfortran_flags.html

1 Like

@FortranFan, perhaps, you should familiarize yourself with the gfortran manual.

@kargl, please don’t say such things in this forum, because it can be seen as disrespectful (we have a Code of Conduct at this forum: Welcome to Discourse) and it assumes that @FortranFan fan is not familiar with the GFortran manual, which is an incorrect assumption (@FortranFan is very much familiar with the GFortran manual), but even if that was correct, you can say the same thing respectfully, for example you can say something like:

@FortranFan, I think this is explained in the GFortran manual, in particular you can try adding the -Wall option. …”

3 Likes

The gfortran -Wall is detecting your problem.
One funny thing is that on my system I don’t obtain (NaN, NaN) but (0.0, 0.0):

2 + 3 = 5
25.0 + 35.0 = 60.0
             (0.00000000,0.00000000)

$ gfortran --version
GNU Fortran (Ubuntu 9.3.0-10ubuntu2) 9.3.0

I don’t know where the numerical result is taken in the memory if result(sum) is not specified… But it seems we have different values at that address…

An interesting question is: why does the compiler only prints a warning? Should it not be an error message? A function which returns nothing is quite strange. If it has a declared type it should return something… either using the name of the function or the result() statement.

2 Likes

Steve, I 100% believe that you didn’t mean it to be disrespectful, and it possibly wasn’t received as such. I don’t think that any of the specific words in that statement were disrespectful. However, the tone could be interpreted as disrespectful or condescending. @certik gave a nice example of how that could have been expressed more gently.

We really don’t know and we can’t assume. Calling another user’s comment “flippant” is also not constructive. If you found that another user’s comment was uninformed or not thought-through, it’s an opportunity to point them (with an URL for example) to the correct part of the documentation. Perhaps even explain why -Wall is more appropriate in this context than -pedantic. It would help other readers here (including myself) as well.

If you found that another user’s comment was provocative or disrespectful in any way, please let the moderators (me, @certik, or @lkedward) know via direct message and we’ll deal with it.

3 Likes

Other’s have already pointed out the two ways to go about correcting the error. What’s really baffling to me is how int_add and real_add managed to actually produce the right result since you made the same error there. Anybody else notice that and have any ideas?

2 Likes

You’re right, I was surprised as well.

2 Likes

I’m fairly certain I’ve made the same mistake before of thinking I’ve set the return value in a function but in fact I have not.

My guess is that it is by coincidence. For the integer and real cases, the result of the addition fits into a single 32bit register; the add op has probably used the same register that is used as the function return value. Without further statements in the function, the sum value is left in the return register so the correct result is returned by coincidence of register choice.
(One of the worst kinds of bug: code is wrong, but works by coincidence.)

I agree it is peculiar; I can’t find anything in the standard interpretation document about the behaviour or validity of functions that don’t set their function result. This is probably because, as you point out, there is no use of such a function in Fortran.

3 Likes

Does it mean that a Fortran compiler:

  • prints an error message when the code breaks an explicit rule of the standard,
  • prints a warning in other problematic cases ?

Good point.

Also, it appears it is -Wreturn-type compiler option that leads the compiler to issue the warnings with the code in the original post.

However, unfortunately the description of this option is missing in the link I provided above nor is it indicated this option is included with -Wall. Is this an area where GCC-gfortran compiler “documentation” can be improved?

Since gfortran is looking for new contributors (see this), perhaps several or many among from the developing community at Fortran-lang can contribute to GCC-gfortran community as well and help improve documentation as needed and help enhance the compiler? After all, gfortran compiler appears to be used heavily by quite a few here.

The main 2 points of my post above were

  1. to use compiler options (I steered myself toward -Wpedantic because that made sense to me) that help with diagnostics (note @ELNS had used gfortran -c arithmetic_mod.f90) and
  2. to bring attention to @ELNS and other readers here they can contribute to open-source initiatives such as GCC-gfortran enhancements as well.

@kargl Just out of curiosity, is “-pedantic” a sort of “historical” thing (as of 2020), as long as gfortran is concerned? I usually use only -Wall -Wextra etc, and was wondering what is the purpose of “-pedantic” some time ago.

On the other hand, is “-pedantic” still useful for other GCC languages (say C)?

Note: just found out -Wreturn-type is a GCC option that applies to gfortran as well
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wreturn-type-Wreturn-typem

GCC “manual” suggests pedantic is a synonym of Wpedantic which is used to “Issue all warnings …” and I didn’t find any mention of any change to handling of twos-complement integers. As much as I’ve referred to GCC/gfortran over the years which is exclusively to try to help other Fortranners online who are using GCC and gfortran in their work, my understanding may be inadequate. Nonetheless, it will be most surprising if such a “warning” option indeed changes integer semantics.

gfortran users will benefit if someone can confirm this is indeed the case and illustrate the impact with a minimal working example (MWE).

c.f. Wikipedia: " In computing, a minimal working example (abbreviated MWE ) is a collection of [source code] (Source code - Wikipedia) and other data files which allow a bug or problem to be demonstrated and reproduced."

The above comment ain’t that for sure. Where is the issue?

   integer :: i, j
   character(len=*), parameter :: fmtz = "(g0,1x,z0)"
   j = 42
   i = iabs(j)
   print fmtz, "i = ", i
   print fmtz, "j = ", j
   if ( i /= j ) error stop "-Wpedantic causes an issue"
   stop "-Wpedantic makes no difference."
end

C:\Temp>ifort /standard-semantics /warn:all /stand:f18 p.f90 /exe:ifort-p.exe
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.1.1.216 Build 20200306
Copyright (C) 1985-2020 Intel Corporation. All rights reserved.

p.f90(4): warning #8891: Specific names for intrinsic procedures are obsolescent in Fortran 2018. [IABS]
i = iabs(j)
-------^
Microsoft (R) Incremental Linker Version 14.25.28612.0
Copyright (C) Microsoft Corporation. All rights reserved.

-out:ifort-p.exe
-subsystem:console
p.obj

C:\Temp>ifort-p.exe
i = 2A
j = 2A
-Wpedantic makes no difference.

C:\Temp>gfortran -Wpedantic p.f90 -o gcc-p.exe

C:\Temp>gcc-p.exe
i = 2A
j = 2A
STOP -Wpedantic makes no difference.

C:\Temp>