Forum

Type mismatch in argument '<arg>' - cannot convert REAL constant to type(dual_num)

  1. Josh Hodson

    I am attempting to integrate Dr. Yu's DNAD module into an existing Fortran code, but getting several compiler errors:

        Error: Type mismatch in argument '<arg>' at (1); passed REAL(8) to TYPE(dual_num)

    The problem occurs in a call to a function that has input arguments of type REAL.  When the conversion to DNAD is made, these input arguments become TYPE(dual_num).  Anywhere in the code that this function is called with constants, I get the above error.

    Example:

        module implicit_type_conversion
            use dual_num_auto_diff
            implicit none

        contains
            subroutine sub1(a)
                type(dual_num), intent(in) :: a
                ! Some code here
            end subroutine sub1
        end module implicit_type_conversion

        program main
            use dual_num_auto_diff
            use implicit_type_conversion
            implicit none
            call sub1(1.0)
        end program main

    Compiler output (gfortran 5.3.0):

        implicit_type_conversion.f90:19:14:
            call sub1(1.0)
                              1
        Error: Type mismatch in argument ‘a’ at (1); passed REAL(4) to TYPE(dual)

    Is there a way to get this to work without having to refactor the original code to explicitly store all REAL arguments in a REAL variable prior to passing it to a function/subroutine?  I have several functions/subroutines that have this problem.  Sometimes they are called with constants (e.g. 1.0), and sometimes they are called with variables (which in the DNAD version have been converted to type(dual_num)).  Any help would be greatly appreciated.

    Thanks,
    Josh

  2. Wenbin Yu

    I am not sure whether this is a work around other than what you have suggested: Define the constants then  pass the constants as arguments should solve the problem. 

    It is not a good programming practices to pass constant number as arguments. 

    And also using 1.0 in a double precision problem defeats the very purpose of double presision. 

    And also, can you try to pass a real (4) constant as angurement to a real(8)  variables? If this does not work, then there it will definitely not work for dual.  

     

     

  3. kshitiz swaroop

    Unfortunately no,

     

    Can you define another subroutine exactly the same, just that it accepts a real input as an argument. with a different name and change the subroutines calling the constants 

    Or, Define something like 

    module implicit_type_conversion
            use dual_num_auto_diff
            implicit none

    PUBLIC sub1
       INTERFACE sub1

        Module procedure sub1_r

        Module Procedure sub1_dual   
        contains
            subroutine sub1(a)
                Real, intent(in) :: a
                ! Some code here
            end subroutine sub1

    subroutine sub1_dual(a)
                Type(dual_num), intent(in) :: a
                ! Some code here
            end subroutine sub1

        
        end module implicit_type_conversion

     

    Hope it helps,

    Kshitiz

     

  4. Josh Hodson

    Thank you for the quick responses!

    Dr. Yu is correct, you cannot pass a real(4) argument as constant to a real(8) variable.  It causes the same compiler error as passing real to type(dual_num).  I am used to C++ where implicit conversions are commonplace, I did not realize this about Fortran.  Thanks for pointing this out.

    Both methods suggested seem to work fine.  I can define the constants as variables in the calling code, or create interfaces for the target function that handle the argument types appropriately.  Thanks for your help!

    Side note: In the code I am working on, we use compiler options to control the precision of the code.  All floating-point variables are declared as "real" with no precision specified, and constants are defined without precision as well.  Then we can control precision by compiler option -fdefault-real-[4|8], so that there is no risk of forgetting to declare floating-point variables as "real*8" or defining constants without the "d0" or equivalent.  Also it maintains consistency in how floating-point variables are declared (no mixing "real*8", real(8), real(kind=...), etc.), which is very helpful for code refactoring such as is required for DNAD integration.

  5. Wenbin Yu

    But once you use constant such as 1.0, you implicitly assume Real(4), then no matter how you define other precession, you only guaranteed to get real(4).


    Emailed forum response from wenbinyu@purdue.edu
  6. Josh Hodson

    If you use -fdefault-real-8, then constants without explicit precision (like 1.0) will be real(8).  See https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html

  7. Wenbin Yu

    That is a neat feature although I never used it myself.


    Emailed forum response from wenbinyu@purdue.edu